兼容性级别从100切换到130会导致锁定或死锁问题吗?

时间:2018-12-10 12:55:05

标签: sql-server deadlock sql-server-2016 compatibility-level

我们当前正在开发环境(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关闭了它。

1 个答案:

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