我们当前正在开发环境(sql server 2016)中测试从兼容性级别(cl)130切换到从100升级的情况。切换之后,我们发现了一些错误:
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:这不是锁升级问题,因为我已为表Tab1关闭了它。
答案 0 :(得分:1)
直接从100切换到130时是否兼容级别 影响锁定,甚至可能导致死锁问题, 以前没有?
直接,不。间接地,是的。阻塞和死锁通常是由于执行计划欠佳而导致的,涉及的数据量超过了当前任务所需的数据量。
当数据库兼容性级别更改为SQL 2014或更高版本时,默认情况下使用新的基数估计器。与较低兼容性级别中使用的传统CE相比,这可能会导致不同的执行计划,更好或更糟。某些查询可能会遭受计划回归的影响。
即使兼容级别更高,也尝试使用ALTER DATABASE SCOPED CONFIGURATION
来使用旧版CE:
USE YourDatabase;
ALTER DATABASE SCOPED CONFIGURATION SET LEGACY_CARDINALITY_ESTIMATION=ON;
如果这缓解了阻塞和死锁,请查看查询计划以获取查询和索引调整机会。需要调优的查询在升级后进一步回归的情况并不少见。另外,您可以尝试打开QUERY_OPTIMIZER_HOTFIXES
选项,由于大量注意,默认情况下此选项处于关闭状态。
如果仅在少数情况下需要旧版CE,请考虑向这些查询添加OPTION (USE HINT('FORCE_LEGACY_CARDINALITY_ESTIMATION'))
查询提示。默认情况下,这将允许您使用最新的CE。