且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何摆脱SQL Server 2005和C#应用程序中的死锁?

更新时间:2023-02-06 22:52:10

我看不到代码中的显式事务作用域,因此我不知道在进行更新时已经使用了哪些锁;也不清楚您正在使用什么隔离级别。但是,在这种情况下最常见的情况是,在同一事务中,较早时您已在要稍后更新的同一行上发出了选择(读锁)。如果两个事务试图做同一件事,这将导致锁升级,并可能导致死锁:

I can't see any explicit transaction scope in your code, so I do not know what locks are already in place when you are doing your update; also it is not clear what isolation level you are using. But the most common scenario in this type of situation is that earlier in the same transaction you have issued a select (read lock) on the same rows that you are trying to update later. This will cause a lock escalation, and can result in a deadlock if two transactions are trying to do the same thing:


  1. 事务A:选择具有读取锁定

  2. 事务B:选择具有读取
    锁定

  3. 事务A:更新-希望将其读取锁定升级为
    写入锁定,但必须等待事务B释放其读取的
    锁定

  4. 事务B:更新-希望将其读取锁定升级为
    写锁,但必须等待事务A释放读取的
    锁。

  1. Transaction A: select with read lock
  2. Transaction B: select with read lock
  3. Transaction A: update - wants to escalate its read lock to a write lock, but has to wait for transaction B to release its read lock
  4. Transaction B: update - wants to escalate its read lock to a write lock, but has to wait for transaction A to release its read lock.

宾果!死锁,因为A和B都在互相等待以释放其现有的读锁,然后才能进行更新。

Bingo! deadlock as both A and B are waiting on each other to release their existing read locks before they can do their update.

为防止这种情况,您需要在选择的内容中添加上锁提示,例如,

To prevent this you need an updlock hint in your select, e.g.,

select * from table with (updlock) where blah blah

这将确保您的选择使用写锁而不是读锁,这将防止并发事务之间的锁升级。

This will ensure your select uses a write lock instead of a read lock, which will prevent lock escalation between concurrent transactions.