如果以相同的顺序访问对象,如何发生死锁?

时间:2013-09-09 11:25:52

标签: sql sql-server transactions database-deadlocks

the MS Technet page on "Minimizing Deadlocks"上,它表示“无法完全避免死锁”。更具体地说,它表明

  

如果所有并发事务以相同的顺序访问对象,则不太可能发生死锁。

这意味着即使所有事务以相同的顺序访问对象,理论上也可能发生死锁。有人可以举例说明如何做到这一点吗?

2 个答案:

答案 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

死锁。

问题是两个连接都可以获取资源上的共享锁,但是当需要将它们转换为独占锁时会相互阻塞。