首页 > 解决方案 > 将兼容级别从 100 切换到 130 会导致锁定或死锁问题吗?

问题描述

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

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

解决方案


兼容级别从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。


推荐阅读