我在SQL Server 2016中拥有三个群集列存储索引(CCI)表。所有这些CCI都基于租户ID处于同一分区方案中。最近,而且前后矛盾,我在从联接到这些表的简单选择语句中陷入僵局。死锁的示例查询:
SELECT TOP 33 r.tenantid
FROM Table_r r
INNER JOIN Table_cm cm ON r.MyKey=cm.MyKey
INNER JOIN Table_pe pe ON r.MyKey=pe.MyKey
WHERE r.TenantId = 69
AND pe.TenantId = 69
AND cm.TenantId = 69
错误信息:
事务(进程ID 56)与另一个进程在通用的可等待对象资源上处于死锁状态,并且被选择为死锁牺牲品。重新运行事务。
线索:
- 如果查询使用CCI以外的其他索引,则不会死锁。
- 如果删除三个tenantid过滤器中的两个,则不会死锁。
- 如果我选择前32位或更低,则不会死锁。
- 如果添加OPTION(MAXDOP 1),则不会死锁。
- 我可以在混乱的PROD副本,PROD只读次要副本和PROD本身中对此进行复制。
- 我无法在DEV或INT中复制此行为。
- 如果我将WITH(NOLOCK)添加到所有3个表联接中,它仍然会死锁
- 查询自身会死锁。当没有其他活动进程时,它将死锁。
- 没有并行性的查询计划不会死锁
我们的PROD版本:
Microsoft SQL Server 2016(SP2-CU5)(KB4475776)-13.0.5264.1(X64)2019年1月10日18:51:38版权所有(c)Windows Server 2012 R2 Standard 6.3(Build 9600)上的Microsoft Corporation Enterprise Edition(64位) :)(管理程序)
如何防止此查询出现死锁?