SQL Server的死锁说明
死锁指南
- 一、了解死锁
- 二、检测并结束死锁
- 2.1、可能死锁的资源
- 三、处理死锁
- 四、最大限度地减少死锁
- 4.1、以相同的顺序访问对象
- 4.2、避免事务中的用户交互
- 4.3、保持交易简短且在一个批次中
- 4.4、使用较低的隔离级别
- 4.5、使用基于行版本控制的隔离级别
- 4.6、使用绑定连接
- 4.7、停止事务
- 总结
一、了解死锁
死锁是导致数据库中的竞争性并发锁,通常在多步骤事务中。
当两个或多个任务永久相互阻止时,每个任务都锁定了其他任务尝试锁定的资源,就会发生死锁。例如:
- 事务 A 获取第 1 行上的共享锁。
- 事务 B 获取第 2 行上的共享锁。
- 事务 A 现在请求第 2 行上的独占锁,并被阻止,直到事务 B 完成并释放第 2 行上的共享锁。
- 事务 B 现在请求第 1 行上的独占锁,并被阻止,直到事务 A 完成并释放它在第 1 行上的共享锁。
事务 A 在事务 B 完成之前无法完成,但事务 B 被事务 A 阻止。此条件也称为循环依赖关系:事务 A 依赖于事务 B,事务 B 通过对事务 A 的依赖来关闭循环。
死锁中的两个事务将永远等待,除非死锁被外部进程打破。SQL Server 数据库引擎死锁监视器定期检查处于死锁状态的任务。如果监视器检测到循环依赖关系,它将选择其中一个任务作为受害者,并在出现错误的情况下终止其事务。这允许其他任务完成其事务。具有因错误而终止的事务的应用程序可以重试该事务,该事务通常在另一个死锁事务完成后完成。
死锁经常与正常阻塞混淆。当一个事务请求锁定另一个事务锁定的资源时,请求事务将等待,直到锁定被释放。默认情况下,除非设置了LOCK_TIMEOUT,否则 SQL Server 事务不会超时。请求事务被阻止,而不是死锁,因为请求事务没有执行任何操作来阻止拥有锁的事务。最终,拥有事务将完成并释放锁,然后请求事务将被授予锁定并继续。死锁几乎可以立即解决,而阻塞理论上可以无限期地持续存在。僵局有时被称为致命的拥抱。
死锁是可能发生在具有多个线程的任何系统上的情况,而不仅仅是在关系数据库管理系统上,并且可能发生在数据库对象上的锁以外的资源上。例如,多线程操作系统中的线程可能会获取一个或多个资源,例如内存块。如果要获取的资源当前由另一个线程拥有,则第一个线程可能必须等待拥有该线程释放目标资源。据说等待线程依赖于该特定资源的拥有线程。在 SQL Server 数据库引擎实例中,会话在获取非数据库资源(如内存或线程)时可能会死锁。
在图中,事务 T1 依赖于表锁资源的事务 T2。同样,事务 T2 依赖于表锁资源的事务 T1。由于这些依赖项形成一个循环,因此事务 T1 和 T2 之间存在死锁。
当对表进行分区并将 的设置设置为 AUTO 时,也会发生死锁。设置为 AUTO 时,通过允许 SQL Server 数据库引擎在 HoBT 级别而不是表级别锁定表分区,并发性会增加。但是,当单独的事务在表中持有分区锁并希望在其他事务分区上的某个位置使用锁时,这会导致死锁。这种类型的死锁可以通过设置为 ;尽管此设置将通过强制对分区进行大量更新以等待表锁定来降低并发性。
二、检测并结束死锁
当两个或多个任务永久相互阻止时,每个任务都锁定了其他任务尝试锁定的资源,就会发生死锁。下图显示了死锁状态的高级视图,其中:
- 任务 T1 锁定了资源 R1(由从 R1 到 T1 的箭头指示),并请求锁定资源 R2(由从 T1 到 R2 的箭头指示)。
- 任务 T2 锁定了资源 R2(由从 R2 到 T2 的箭头指示),并请求锁定资源 R1(由从 T2 到 R1 的箭头指示)。
- 由于在资源可用之前,这两个任务都无法继续,并且在任务继续之前无法释放这两个资源,因此存在死锁状态。
SQL Server 数据库引擎会自动检测 SQL Server 中的死锁周期。SQL Server 数据库引擎选择其中一个会话作为死锁受害者,当前事务将终止,并显示错误以打破死锁。
2.1、可能死锁的资源
每个用户会话可能代表其运行一个或多个任务,其中每个任务可能获取或等待获取各种资源。以下类型的资源可能会导致阻塞,从而导致死锁。
-
锁。等待获取资源(如对象、页面、行、元数据和应用程序)的锁可能会导致死锁。例如,事务 T1 在行 r1 上具有共享 (S) 锁,并且正在等待在 r2 上获取独占 (X) 锁。事务 T2 在 r2 上具有共享 (S) 锁,并且正在等待在行 r1 上获取独占 (X) 锁。这会导致锁定循环,其中 T1 和 T2 相互等待对方释放锁定的资源。
-
工作线程。等待可用工作线程的排队任务可能会导致死锁。如果排队的任务拥有阻止所有工作线程的资源,则会导致死锁。例如,会话 S1 启动事务并在行 r1 上获取共享 (S) 锁,然后进入睡眠状态。在所有可用工作线程上运行的活动会话正在尝试获取行 r1 上的独占 (X) 锁。由于会话 S1 无法获取工作线程,因此它无法提交事务并释放行 r1 上的锁。这会导致死锁。
-
内存。当并发请求正在等待可用内存无法满足的内存授予时,可能会发生死锁。例如,两个并发查询 Q1 和 Q2 作为用户定义的函数执行,分别获取 10 MB 和 20 MB 的内存。如果每个查询需要 30 MB,总可用内存为 20 MB,则 Q1 和 Q2 必须等待对方释放内存,这会导致死锁。
-
与并行查询执行相关的资源。与交换端口关联的协调器、生产者或使用者线程可能会相互阻塞,从而导致死锁,通常是在包含至少一个不属于并行查询一部分的其他进程时。此外,当并行查询开始执行时,SQL Server 会根据当前工作负荷确定并行度或工作线程数。如果系统工作负荷意外更改(例如,新查询开始在服务器上运行或系统工作线程不足),则可能会发生死锁。
-
多个活动结果集 (MARS) 资源。用户资源、会话互斥锁、事务互斥锁等这些资源用于控制 MARS 下多个活动请求的交错。
为了使任务在 MARS 下运行,它必须获取会话互斥锁。如果任务在事务下运行,则必须获取事务互斥锁。这保证在给定会话和给定事务中一次只有一个任务处于活动状态。获取所需的互斥锁后,任务就可以执行。当任务完成或在请求中间产生时,它将首先释放事务互斥锁,然后以相反的获取顺序释放会话互斥锁。但是,这些资源可能会发生死锁。在以下伪代码中,两个任务(用户请求 U1 和用户请求 U2)在同一会话中运行。
从用户请求 U1 执行的存储过程已获取会话互斥锁。如果存储过程需要很长时间才能执行,则 SQL Server 数据库引擎假定存储过程正在等待用户的输入。用户请求 U2 正在等待会话互斥锁,而用户正在等待来自 U2 的结果集,U1 正在等待用户资源。这是死锁状态,逻辑上说明为:
三、处理死锁
当 SQL Server 数据库引擎实例选择某个事务作为死锁受害者时,它将终止当前批处理,回滚该事务,并向应用程序返回错误消息 1205。
由于提交 Transact-SQL 查询的任何应用程序都可以被选为死锁受害者,因此应用程序应具有可以捕获错误消息 1205 的错误处理程序。如果应用程序未捕获错误,则应用程序可以在不知道其事务已回滚并可能发生错误的情况下继续操作。
实现捕获错误消息 1205 的错误处理程序允许应用程序处理死锁情况并采取补救措施(例如,自动重新提交死锁中涉及的查询)。通过自动重新提交查询,用户无需知道发生了死锁。
在重新提交查询之前,应用程序应短暂暂停。这使死锁中涉及的其他事务有机会完成并释放构成死锁循环一部分的锁。这样可以最大程度地降低在重新提交的查询请求其锁时再次发生死锁的可能性。
四、最大限度地减少死锁
尽管无法完全避免死锁,但遵循某些编码约定可以最大程度地减少生成死锁的可能性。最小化死锁可以提高事务吞吐量并减少系统开销,因为事务较少:
- 回滚,撤消事务执行的所有工作。
- 由应用程序重新提交,因为它们在死锁时已回滚。
要帮助最大程度地减少死锁,请执行以下操作:
- 以相同的顺序访问对象。
- 避免事务中的用户交互;保持交易简短且批量。
- 使用较低的隔离级别。
- 使用基于行版本控制的隔离级别。将数据库选项设置为启用已提交的读取事务以使用行版本控;使用快照隔离。
- 使用绑定连接。
4.1、以相同的顺序访问对象
如果所有并发事务都以相同的顺序访问对象,则不太可能发生死锁。例如,如果两个并发事务在表上获取锁,然后在表上获得锁,则一个事务在表上被阻止,直到另一个事务完成。第一个事务提交或回滚后,第二个事务将继续,并且不会发生死锁。对所有数据修改使用存储过程可以标准化访问对象的顺序。
4.2、避免事务中的用户交互
避免编写包含用户交互的事务,因为无需用户干预即可运行的批处理的速度比用户必须手动响应查询(例如回复应用程序请求的参数提示)的速度快得多。例如,如果事务正在等待用户输入,并且用户周末去吃午饭甚至回家,则用户会延迟事务完成。这会降低系统吞吐量,因为事务持有的任何锁仅在提交或回滚事务时释放。即使没有出现死锁情况,访问相同资源的其他事务也会在等待事务完成时被阻止。
4.3、保持交易简短且在一个批次中
当多个长时间运行的事务在同一数据库中同时执行时,通常会发生死锁。事务时间越长,独占锁或更新锁的持有时间就越长,从而阻止其他活动并导致可能的死锁情况。
将事务保存在一个批次中可最大程度地减少事务期间的网络往返,从而减少完成事务和释放锁定时可能出现的延迟。
4.4、使用较低的隔离级别
确定事务是否可以在较低的隔离级别运行。实现 read commit 允许事务读取先前由另一个事务读取(未修改)的数据,而无需等待第一个事务完成。与较高的隔离级别(如可序列化)相比,使用较低的隔离级别(如已提交的读取)保留共享锁的持续时间更短。这减少了锁定争用。
4.5、使用基于行版本控制的隔离级别
当数据库选项设置为 ON 时,在读取提交隔离级别下运行的事务在读取操作期间使用行版本控制而不是共享锁。
快照隔离还使用行版本控制,在读取操作期间不使用共享锁。在事务可以在快照隔离下运行之前,必须设置数据库选项ALLOW_SNAPSHOT_ISOLATIONON。
实现这些隔离级别,以最大程度地减少读取和写入操作之间可能发生的死锁。
4.6、使用绑定连接
使用绑定连接,同一应用程序打开的两个或多个连接可以相互协作。辅助连接获取的任何锁都像由主连接获取一样保存,反之亦然。因此,它们不会相互阻塞。
4.7、停止事务
在死锁方案中,受害事务会自动停止并回滚。在死锁情况下无需停止事务。
总结
有些应用程序依赖于读取提交隔离的锁定和阻止行为。对于这些应用程序,在启用使用基于行版本控制的隔离级别之前需要进行一些更改。
相关文章:

SQL Server的死锁说明
死锁指南一、了解死锁二、检测并结束死锁2.1、可能死锁的资源三、处理死锁四、最大限度地减少死锁4.1、以相同的顺序访问对象4.2、避免事务中的用户交互4.3、保持交易简短且在一个批次中4.4、使用较低的隔离级别4.5、使用基于行版本控制的隔离级别4.6、使用绑定连接4.7、停止事…...
关于#define的一些小知识
目录 一,#define的声明格式: 二,#define宏的作用是为了完成替换 #define的替换规则: 三,#define使用时常犯的错误 四,宏与函数的比较 4.1,什么时候使用宏? 4.1,…...

rabbitmq普通集群与镜像集群搭建
1.准备三台centos7主机,并关闭防火墙与selinux 2.安装rabbitmq环境必备的Erlang(以下所有操作三台主机均需要执行) 执行以下命令下载配置erlang yum源 curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | sudo bash使用yum命…...
session和jwt哪个更好
session和jwtsession优点缺点jwt优点缺点总结session 优点 原理简单,易于学习。用户信息存储在服务端,可以快速封禁某个用户。 缺点 占用服务端内存,硬件成本高。多进程,多服务器时,不好同步-需要使用第三方缓存&a…...

基于TPU-MLIR实现UNet模型部署-决赛答辩02
队伍:AP0200023 目录 初赛 一、 模型导出优化 1.1 直接倒出原始模型并转换 1.2 导出模型前处理 1.2.1 导出Resize 1.2.2 导出归一化 1.3导出模型后处理 1.3.1导出 Resize 与 1.3.2导出 ArgMaxout 1.3.3导出特征转RGB 复赛 一、 确定baseline 二、优化模…...

Maven高级-分模块开发依赖管理
Maven高级-分模块开发&依赖管理1,分模块开发1.1 分模块开发设计1.2 分模块开发实现1.2.1 环境准备1.2.2 抽取domain层步骤1:创建新模块步骤2:项目中创建domain包步骤3:删除原项目中的domain包步骤4:建立依赖关系步骤5:编译maven_02_ssm项目步骤6:将项目安装本地…...

《安富莱嵌入式周报》第308期:开源带软硬件安全认证的PLC设计,开源功率计,可靠PID实现,PR2机器人设计文件全开源,智能手表设计WASP-OS
周报汇总地址:嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版: https://www.bilibili.com/video/BV1F24y157QE 《安富莱嵌入式周报》第308期:开源带软…...

代码随想录算法训练营第五十六天 | 583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结
583. 两个字符串的删除操作 动规五部曲 1、确定dp数组(dp table)以及下标的含义 dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。 2、确定递推…...

Sip协议
简介 SIP(Session Initiation Protocol,会话初始协议)是一个用于建立、更改和终止多媒体会话的应用 层控制协议,其中的会话可以是 IP 电话、多媒体会话或多媒体会议。SIP 是 IETF 多媒体数据和控 制体系结构的核心协议࿰…...
RandomAccessFile类 断点续传
文章目录学习链接RandomAccessFile构造方法实现的接口DataOutputDataInputAutoCloseable重要的方法多线程读写同一个文件(多线程复制文件)代码1代码2断点续传FileUtils学习链接 RandomAccessFile详解 Java IO——RandomAccessFile类详解 java多线程-断点…...
SpringCloud微服务技术栈的注册中心Eureka
文章目录SpringCloud微服务技术栈的注册中心Eureka简介Eureka特点操作步骤环境准备创建Eureka Server注册服务提供方调用服务消费方总结SpringCloud微服务技术栈的注册中心Eureka 简介 在微服务架构中,服务的数量庞大,而且每个服务可能会有多个实例。此…...
Unity最新热更新框架 hybridclr_addressable
GitHub:YMoonRiver/hybridclr_addressable: 开箱即用的商业游戏框架,集成了主流的开发工具。将主流的GameFramework修改,支持Addressable和AssetBundle,已完善打包工具和流程。 (github.com) # 新增GameFramework Addressables 开箱即用 # 新…...

【c语言】一维数组***特性、存储原理
创作不易,本篇文章如果帮助到了你,还请点赞支持一下♡>𖥦<)!! 主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步! 给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ…...

[oeasy]python0133_[趣味拓展]好玩的unicode字符_另类字符_上下颠倒英文字符
另类字符 回忆上次内容 上次再次输出了大红心♥ 找到了红心对应的编码黑红梅方都对应有编码 原来的编码叫做 ascii️ \u这种新的编码方式叫unicode包括了 中日韩字符集等 各书写系统的字符集 除了这些常规字符之外 还有什么好玩的东西呢? 颠倒字符 这个网站可以…...
找凶手,定名次,字符串旋转,杨氏矩阵
1.找凶手问题: //题目名称: //猜凶手 //题目内容: //日本某地发生了一件谋杀案,警察通过排查确定凶手必为4个嫌疑犯的一个。 //以下为4个嫌疑犯的供词: //A说:不是我 //B说:是C //C说ÿ…...

Python 进阶指南(编程轻松进阶):十四、实践项目
原文:http://inventwithpython.com/beyond/chapter14.html 到目前为止,这本书已经教会了你编写可读的 Python 风格代码的技巧。让我们通过查看两个命令行游戏的源代码来实践这些技术:汉诺塔和四人一排。 这些项目很短,并且基于文…...
Redis的五种数据类型及应用场景
Redis是一个开源的key-value数据库。 五种数据类型 String,List, Set,SortedSet,Hash List类型可以存储多个String。 Set类型可以存储不同的String。 SortedSet可以存储String的排序。 Hash可以存储多个key-value对。 String …...

c++List的详细介绍
cList详细使用 write in front 作者: 不进大厂不改名 专栏: c 作者简介:大一学生 希望能向其他大佬和同学学习! 本篇博客简介:本文主要讲述了一种新容器list的使用方法,相信你在学了后,能够加深…...

Heap堆的升序排序
在heap堆中,大根堆是一种特殊的堆,它满足下列性质:对于任意一个非叶子节点i,其左右子节点的值均小于等于它本身的值。 在大根堆中,堆顶元素永远是值最大的元素,所以将堆顶元素不断取出来,就相当…...

小程序开发收费价目表
小程序作为一种新兴应用形式,正在逐渐成为企业和个人推广、运营的重要手段。然而,小程序开发的价格因项目规模和复杂程度差异较大,令不少人望而却步。本文将从小程序开发的相关因素入手,探讨小程序开发的价格范围和算法。 一、小…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...

五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...