如何解决 SQL Server 死锁 - 一旦更改顺序和缩短查询用尽?

Posted

技术标签:

【中文标题】如何解决 SQL Server 死锁 - 一旦更改顺序和缩短查询用尽?【英文标题】:How to resolve SQL Server deadlocks - once changing order and shortening queries is exhausted? 【发布时间】:2013-01-28 14:38:17 【问题描述】:

我有两个假设的查询:

UPDATE BankAccounts SET HomePhone = '+1 252-555-0912' 
WHERE AccountNumber = 14400000619

SELECT * FROM BankAccounts 
WHERE HomePhone = '555-1212'

在没有额外索引的假设表上:

CREATE TABLE BankAccounts 
( 
   AccountNumber bigint NOT NULL PRIMARY KEY CLUSTERED,
   FirstName nvarchar(50) NOT NULL,
   MiddleName nvarchar(50) NULL,
   LastName nvarchar(50) NOT NULL,
   HomePhone varchar(50) NULL,
   IsClosed tinyint DEFAULT 0
)

一切都会好起来的。如果我在HomePhone 上添加索引:

CREATE INDEX IX_BankAccounts_HomePhone ON BankAccounts 
( HomePhone)

现在我的SELECT 声明可能成为僵局的受害者:

Transaction(进程 ID 169)与另一个进程在锁资源上死锁,并被选为死锁牺牲品。重新运行事务。

常见的建议是:

以相同的顺序访问表 尽可能缩短交易时间

这种情况除外:

我正在以相同的顺序访问(一个)表(1 选择 1 是 1) 交易是一个单一语句;我不能比这更短了

消除这种死锁的长期解决方案是什么?

我正在考虑将我的交易隔离级别更改为READ UNCOMMITTED(即消除完整性),但因为我实际上是在处理一个金融系统,所以我很犹豫是否允许客户撤回他的整个余额两次。

我能找到的唯一其他解决方案来自KB Article 83252:

SQL Server 技术公告 - 如何解决死锁

...死锁无法避免。这就是为什么应该设计前端应用程序来处理死锁。

在设计良好的应用程序中,前端应用程序应捕获 1205 错误,重新连接到 SQL Server,然后重新提交事务。

我猜是在说:“不能赢;不要尝试”

还有什么?

【问题讨论】:

【参考方案1】:

如果将SELECT * 替换为列列表(或考虑所有列),然后将它们作为INCLUDEd columns 添加到索引中,则SELECT 查询将不需要查询聚集索引去完成。然后SELECT 可以一直运行到完成。

如果您不想这样做,那么与其更改整个隔离级别,我会考虑在SELECT 上使用locking hint 是否合适。您需要仔细考虑适当的提示是NOLOCK 还是READPAST(在理想情况下,有一种方法可以指定READPAST,但可以获得有关是否实际发生任何跳过行的信息)。

当然SNAPSHOTisolation也可以考虑(如果没有锁就没有死锁)。


(贪婪的惩罚者也可以考虑在SELECT 语句上使用TABLOCKX。它可以防止死锁并确保您读取存在的行,但会严重影响并发)

【讨论】:

在大型仓库应用程序中,我通过序列化有问题的操作“解决”了一些令人讨厌的死锁问题。这些操作中的每一个都尝试锁定相同的单个记录。我想这相当于你的 TABLOCKX? @VincentVancalbergh - 是的,这实际上是一种要求序列化的本地方式。【参考方案2】:

赢不了;不要尝试

没错。您看到的可能是read-write 死锁(没有死锁图只是我们的推测)。 因为您正在做正确的事情(即,您确实有正确的索引),因此反向顺序访问恰好发生。即使您访问不同的密钥(查找一部手机,更新另一部手机),由于哈希冲突,您仍然在玩a game of probabilities。

您可以接受死锁或诉诸snapshot isolation 模型。

【讨论】:

以上是关于如何解决 SQL Server 死锁 - 一旦更改顺序和缩短查询用尽?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 事务 (ID) 死锁

一个SQL Server 2008 R2 死锁的问题解决

SQL Server 死锁的告警监控

解决sql server死锁

SQL Server死锁产生原因及解决办法

SQL Server死锁的解决过程