sql-server - 将兼容级别从 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 关闭了它。
解决方案
兼容级别从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。
推荐阅读
- javascript - Cookie 解析器的 "res.cookie('cookieName', {cookieData}); 没有设置 cookie
- c# - 方法擦除:为什么说派生类的方法隐藏了基类,反之呢?
- reactjs - 使用 UUID 作为列表键会导致 React 中不必要的重新渲染吗?
- neo4j - neo4j 属性值可以是字典吗
- c++ - IShellDispatch NameSpace-call 失败,不知道为什么
- react-native - 卡片中的阴影效果
- java - 如何筛选具有完全水平尺寸的完整垂直尺寸?
- c# - OtpSharp 不与谷歌身份验证器一起使用
- c# - 在 IEntity 中找不到泛型类型或命名空间名称“T”
- odoo-11 - 如何在 Odoo V11 的树视图中添加“分组依据”?