5

“最小化死锁”的 MS Technet 页面上,它说“无法完全避免死锁”。更具体地说,它指出

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

这意味着理论上可能会发生死锁,即使所有事务都以相同的顺序访问对象。有人可以举一个例子说明这怎么可能吗?

4

2 回答 2

3

只是为了提供一个简单的代码示例来进一步查尔斯的回答

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

僵局。

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

于 2013-09-09T12:15:21.910 回答
3

一种方法是在使用隔离级别可序列化时。

如果您有父子关系,例如在具有客户、客户帐户以及这些帐户的个人财务借方和贷方的会计数据库中,则:

您有一个数据库事务,其中包含子表中的多个平衡借方和贷方条目,以及客户表中帐户余额的伴随更新。

在可序列化的隔离级别,为了防止所谓的幻读,数据库引擎对 SQL 语句必须读取的所有记录(在本例中为贷记表和借记表)设置范围锁。这确保了在此 Tx 计算新的客户余额时,没有其他交易可以将新的贷方或借方插入表中。任何插入新贷方或借方的尝试都会被锁阻止。

同时,第一个 Tx 也被阻塞,因为另一个插入 Tx 将锁定 Customer Table 行,因为它还需要更新客户余额。在提交整个 Tx 之前,锁不会释放,因此两个事务都相互阻塞......死锁。

于 2013-09-09T11:47:35.560 回答