SQL Server - 5 种死锁类型及避免死锁的方法

SQL Server中的5种死锁类型

1)书签查找死锁(Bookmark lookup deadlock)

书签查找是SQL Server中常见的死锁。它是由于select语句和DML(插入、更新和删除)语句之间的冲突而发生的。通常,SQLServer选择select语句作为死锁牺牲品,因为它不会导致数据更改并且回滚很快。为避免书签查找,您可以使用覆盖索引。您也可以在select语句中使用NOLOCK查询提示,但它会读取未提交的数据。

2) 范围扫描死锁(Range scan deadlock)

有时,我们在服务器级别或会话级别使用SERIALIZABLE隔离级别。它是用于并发控制的限制性隔离级别,可以创建范围扫描锁而不是页级或行级锁。在SERIALIZABLE隔离级别中,如果数据被修改但等待在事务中提交,用户将无法读取数据。同样,如果一个事务读取数据,另一个事务不能修改它。它提供了最低的并发性,因此我们应该在特定的应用程序需求中使用此隔离级别。

3)级联约束死锁(Cascading constraint deadlock)

SQL Server通过外键约束使用表之间的父子关系。在这种情况下,如果从父表中更新或删除记录,则需要对子表进行必要的锁定以防止出现孤立记录。要消除这些死锁,应该始终先修改子表中的数据,然后再修改父数据。还可以使用DELETE CASCADE或UPDATECASCADE选项直接处理父表。还应该在外键列上创建适当的索引。

4)查询内并行死锁(Intra-query parallelism deadlock)

一旦用户向SQL查询引擎提交查询,查询优化器就会构建优化的执行计划。它可以根据查询成本、最大并行度(MAXDOP)和并行成本阈值以串行或并行顺序执行查询。

在并行模式下,SQLServer分配多个线程。有时对于并行模式下的大型查询,这些线程开始相互阻塞。最终,它转化为死锁。在这种情况下,您需要查看执行计划以及并行配置的MAXDOP和成本阈值。您还可以在会话级别指定MAXDOP来解决死锁情况。

5)反向对象顺序死锁 (Reverse object order deadlock)

在这种类型的死锁中,多个事务在T-SQL中以不同的顺序访问对象。这会导致每个会话的资源阻塞并将其转换为死锁。所以按逻辑顺序访问对象,以免导致死锁情况。

避免死锁的最佳方法

1. 尽量缩短交易时间; 这将避免在事务中长时间持有锁。

2. 在多个事务中以类似的逻辑方式访问对象。

3. 创建覆盖索引以减少死锁的可能性。

4. 创建索引以匹配外键列。 这样,您可以消除由于级联引用完整性而导致的死锁。

5. 使用SET DEADLOCK_PRIORITY会话变量设置死锁优先级。 如果设置死锁优先级,SQLServer会终止死锁优先级最低的会话。

6. 使用try-catch块利用错误处理。 您可以捕获死锁错误并在死锁牺牲品的情况下重新运行事务。

7. 将隔离级别更改为READ COMMITTED SNAPSHOT ISOLATION或SNAPSHOT ISOLATION。 这会更改SQLServer锁定机制。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容