我对 SQL Server 中的锁定的理解是,如果一个进程在索引中的资源 ega 键行上持有排它 (X) 锁,则另一个进程无法获取同一资源上的共享 (S) 锁,必须等待它被发布。
我一直在尝试演示一个修复程序,用于解决访问同一个表的 2 个不同存储过程之间的死锁,一个使用显式事务来包装一个 SELECT 然后一个 DELETE,另一个只执行 SELECT 而没有显式事务. 这些都发生在 READ COMMITTED 事务隔离级别下。
我完成了在 2 个 SSMS 查询窗口中模拟每个过程的步骤,并查询 sys.dm_tran_locks 以查看每个步骤后持有和等待的锁。
我希望有人解释为什么,尽管有时我确实会遇到预期的死锁,但并非总是如此,而且我可以看到 X 锁已被授予一个连接,而我仍然可以从另一个连接中进行选择。
该演示是人为的,以及在非聚簇索引上拆分 SELECT 的原因,以获取聚簇键值,其中 SELECT 使用聚簇键从聚簇索引中读取其他列(并将两个选择包装在显式事务中HOLDLOCK 在第一个)是模拟我的真实世界查询的实际查询计划,它在非聚集索引上寻找并在聚集索引上执行键查找。我需要展示当读写连接上的 DELETE 查询与只读连接上的 SELECT 冲突时会发生什么
测试数据库不允许 SNAPSHOT ISOLATION 或 READ COMMITTED SNAPSHOT,并且两个连接都已显式设置为 READ COMMITTED 事务隔离级别,因此应该需要共享锁来读取行。
我已经在我的本地机器上使用 SQL2017 CU9(在 64 位 Windows 10 Enterprise build 16299 上)、在带有 SQL2017 CU7 的服务器上(在 Windows Server 2016 Standard build 14393 上)以及带有 SQL2016 sp1-CU2(在 Windows Server 上)的服务器上进行了测试2012 R2 标准版本 …