在the MS Technet page on "Minimizing Deadlocks"上,它表示“无法完全避免死锁”。更具体地说,它表明
如果所有并发事务以相同的顺序访问对象,则不太可能发生死锁。
这意味着即使所有事务以相同的顺序访问对象,理论上也可能发生死锁。有人可以举例说明如何做到这一点吗?
答案 0 :(得分:3)
一种方法是使用Isolation Level Serializable。
如果您有父子关系,例如在具有客户,客户帐户以及个人财务借记和信用额的会计数据库中,那么:
您有一个数据库事务,其中包含子表中的多个平衡借记和贷记条目,以及客户表中帐户余额的随附更新。
在可序列化的隔离级别,为了防止所谓的幻像读取,数据库引擎会在SQL语句必须读取的所有记录上放置范围锁(在本例中为信用卡和借记表)。这确保了在此Tx计算新客户余额时,没有其他交易可以在表中插入新的信用或借记。锁定会阻止任何插入新信用卡或借记卡的尝试。
同时,第一个Tx也被阻止,因为另一个插入Tx将锁定Customer Table行,因为它还需要更新客户余额。在整个Tx提交之前,锁没有释放,因此两个事务都相互阻塞......死锁。
答案 1 :(得分:3)
只是为Charles的回答提供一个简单的代码示例
CREATE TABLE T(X INT)
然后在两个并发连接中运行
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT * FROM T
WAITFOR DELAY '00:00:10'
INSERT INTO T VALUES(1)
COMMIT
死锁。
问题是两个连接都可以获取资源上的共享锁,但是当需要将它们转换为独占锁时会相互阻塞。