我们目前正在我们的开发环境 (sql server 2016) 中测试从 100 升级到兼容级别 (cl) 130 的切换。切换后我们注意到一些错误:
could not execute batch command.[SQL: SQL not available] Transaction (Process ID 54) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
经过一些研究、跟踪和调试,我能够确认我们确实遇到了死锁问题。我们使用 .net 应用程序,它使用 nhibernate 访问数据库。一些内部任务(在 .net 应用程序中)可以为我们设置并行性以更快地完成。这些任务通常以不可能出现(行)死锁的方式分配它们的工作量。即任务 1 和任务 2 可以大致同时访问表 A 和表 B,但它们永远不会访问每个表中的相同行。
这些任务调用一些存储过程,它们执行一些简单的操作,例如:
UPDATE dbo.Tab1
SET dbo.Tab1.Col1 = 'ValueY'
FROM dbo.Tab2
JOIN dbo.Tab3
JOIN dbo.Tab4
…
WHERE Tab1.Col.2 = 'ValueX'
本质上,这将通过 Tab1 运行,搜索要更新的行并更新这些行。
这一切在兼容级别(cl)100 下运行良好。切换到 cl 130 后,我们有时会出现死锁,我们以前没有遇到过。
死锁图显示了同一对象 id/hobt id 上的两个 Key 锁,其中两个不同的服务器进程持有一个 X-Lock 并请求一个 U。
如果我在表 Tab1 中添加不相关的行,对于这个特定的测试,它会将页数增加到 23,并且没有更多问题。
我读过,这整个问题可能是由少量的行/页引起的。与具有数百万行的表相比,优化器/服务器的行为不同,这会导致不同的锁定行为并可能导致死锁。
但这并不能回答我的问题:兼容性级别从 100 切换到 130 时是否会直接影响锁定,甚至可能导致死锁问题,以前没有?
PS:这不是锁升级问题,因为我已经为 Table Tab1 关闭了它。