首页 > 数据库 >SQL Server 的死锁

SQL Server 的死锁

时间:2024-09-16 21:15:29浏览次数:1  
标签:事务 Server 会话 死锁 线程 SQL

死锁经常与正常阻塞混淆。当一个事务请求对另一个事务锁定的资源加锁时,请求加锁的事务会等待直到锁被释放。默认情况下,除非设置了 LOCK_TIMEOUT,否则 SQL Server 事务不会超时。请求事务被阻塞,而不是死锁,因为请求事务没有做任何事情来阻塞持有锁的事务。最终,持有锁的事务将完成并释放锁,然后请求事务将获得锁并继续。死锁几乎可以立即解决,而阻塞理论上可以无限期地持续下去。

 

死锁可能发生在任何有多个线程的系统中,而不仅仅是关系数据库管理系统,而且可能发生在数据库对象锁以外的资源上。例如,多线程操作系统中的线程可能会获取一个或多个资源,如内存块。如果正在获取的资源当前为另一个线程所有,则第一个线程可能需要等待拥有资源的线程释放目标资源。等待的线程对拥有该特定资源的线程具有依赖性。在 SQL Server 数据库引擎实例中,会话在获取内存或线程等非数据库资源时可能会出现死锁。

 

当对表进行分区并将 alter table 的 lock_escalation 设置为 auto 时,也可能出现死锁。当 lock_escalation 设置为 auto 时,由于允许 sql server 数据库引擎在 hobt 级别而不是在表级别锁定表分区,因此并发性会提高。但是,当不同事务在表中持有分区锁,并希望在其他事务分区的某个地方获得锁时,就会导致死锁。将 lock_escalation 设置为 table 可以避免这种死锁;不过,这种设置会降低并发性,因为它会迫使分区的大型更新等待表锁。

 

可能造成死锁的资源

每个用户会话都可能有一个或多个任务在运行,每个任务都可能获取或等待获取资源。以下类型的资源可能会导致阻塞,从而造成死锁。

1.锁

  等待获取对象、页、行、元数据和应用程序等资源的锁可能会导致死锁。

2.工作线程

  等待可用工作线程的队列任务可能会导致死锁。如果队列任务拥有的资源阻塞了所有工作线程,就会导致死锁。例如,会话 S1 启动事务并获得行 r1 上的共享 (S) 锁,然后进入休眠状态。在所有可用工作线程上运行的活动会话正试图获取 r1 行上的独占 (X) 锁。由于会话 S1 无法获取工作线程,因此它无法提交事务并释放 r1 行上的锁。这就导致了死锁。

3.内存

  当并发请求等待的内存授予无法用可用内存满足时,就会出现死锁。例如,两个并发查询 Q1 和 Q2 作为用户定义函数执行,分别获取 10 MB 和 20 MB 内存。如果每个查询需要 30 MB,而可用内存总量为 20 MB,那么 Q1 和 Q2 必须等待对方释放内存,从而导致死锁。

4.并行查询执行相关资源。

  与交换端口相关联的协调者、生产者或消费者线程可能会相互阻塞,导致死锁,通常是在包括至少一个不属于并行查询的其他进程时。此外,当并行查询开始执行时,SQL Server 会根据当前的工作量确定并行程度或工作线程的数量。如果系统工作量发生意外变化,例如服务器上开始运行新查询或系统工作线程用完,就可能出现死锁。

5.多活动结果集 (MARS) 资源

这些资源用于控制 MARS 下多个活动请求的交错。

  ·用户资源。

    当线程在等待可能由用户应用程序控制的资源时,该资源会被视为外部或用户资源,并被视为锁。

  ·会话mutex。

    在一个会话中运行的任务是交错的,这意味着在给定时间内,该会话下只能运行一个任务。在任务运行之前,它必须拥有对会话互斥器的独占访问权限。

  ·事务mutex。

    在一个事务中运行的所有任务都是交错的,这意味着在给定时间内,只有一个任务能在事务下运行。在任务运行之前,它必须拥有对事务互斥器的独占访问权限。

 

任务要在 MARS 下运行,必须获得会话mutex。如果任务在事务中运行,则必须获取事务mutex。这就保证了在给定会话和给定事务中,同一时间只有一个任务处于活动状态。获得所需的mutex后,任务就可以执行了。当任务完成或在请求中途放弃时,它将首先释放事 mutex,然后按获取的相反顺序释放会话mutex。然而,这些资源可能会出现死锁。在下面的伪代码中,用户请求 U1 和用户请求 U2 这两个任务运行在同一个会话中。

U1:    Rs1=Command1.Execute("insert sometable EXEC usp_someproc");  
U2:    Rs2=Command2.Execute("select colA from sometable");

用户请求 U1 执行的存储过程已获得会话mutex。如果存储过程需要很长时间才能执行,SQL Server 数据库引擎会认为存储过程正在等待用户的输入。用户请求 U2 在等待会话mutex时,用户正在等待 U2 的结果集,而 U1 正在等待用户资源。这种死锁状态在逻辑上可表示为

 

 

死锁检测

死锁检测由锁监控线程执行,该线程会定期启动对 SQL Server 数据库引擎实例中所有任务的搜索。以下描述了搜索过程:

·默认时间间隔为 5 秒。

·如果锁监控线程发现死锁,死锁检测时间间隔会从 5 秒缩短到 100 毫秒,具体取决于死锁发生的频率。

·如果锁监控线程不再发现死锁,SQL Server 数据库引擎会将搜索间隔延长至 5 秒。

·如果检测到死锁,则假定下一个必须等待锁的线程正在进入死锁周期。检测到死锁后的头几次锁等待将立即触发死锁搜索,而不是等待下一次死锁检测间隔。例如,如果当前时间间隔为 5 秒,检测到死锁,那么下一次锁等待将立即启动死锁检测。如果这个锁等待是死锁的一部分,它将立即被检测到,而不是在下一次死锁搜索时被检测到。

 

SQL Server 数据库引擎通常只执行定期死锁检测。由于系统中遇到的死锁数量通常很少,因此定期死锁检测有助于减少系统中死锁检测的开销。

 

当锁监控器对某个特定线程启动死锁搜索时,它会识别线程正在等待的资源。然后,锁监控器会找到该特定资源的所有者,并递归地继续对这些线程进行死锁搜索,直到找到循环为止。以这种方式确定的循环会形成死锁。

 

检测到死锁后,SQL Server 数据库引擎会选择其中一个线程作为死锁受害者,从而结束死锁。SQL Server 数据库引擎会终止该线程正在执行的当前批处理,回滚死锁受害者的事务,并向应用程序返回 1205 错误。回滚死锁受害者的事务会释放事务持有的所有锁。这样,其他线程的事务就可以解除锁定并继续运行。1205 死锁受害者错误会在错误日志中记录涉及死锁的线程和资源信息。

 

默认情况下,SQL Server 数据库引擎会选择运行回滚成本最低的事务的会话作为死锁受害者。另外,用户也可以使用 SET DEADLOCK_PRIORITY 语句指定死锁情况下会话的优先级。DEADLOCK_PRIORITY 可以设置为 LOW、NORMAL 或 HIGH,也可以设置为范围(-10 至 10)内的任意整数值。死锁优先级默认为 NORMAL。如果两个会话的死锁优先级不同,则选择优先级较低的会话作为死锁受害者。如果两个会话的死锁优先级相同,则选择回滚成本最低的事务会话。如果参与死锁循环的会话具有相同的死锁优先级和相同的成本,则随机选择一个受害者。

 

在使用 CLR 时,死锁监视器会自动检测 managed procedures 中访问的同步资源(死锁器、读写锁和线程连接)的死锁。不过,死锁是通过在被选中为死锁受害者的存储过程中抛出异常来解决的。需要注意的是,异常不会自动释放受害者当前拥有的资源;必须明确释放这些资源。与异常行为一致,用于识别死锁受害者的异常可以被捕获并解除。

 

死锁信息工具

要查看死锁信息,SQL Server 数据库引擎以 system_health xEvent 会话、两个trace标志和 SQL Profiler 中的死锁图事件的形式提供监控工具。

官方推荐使用死锁扩展事件。

SQL Profiler 会创建trace,但trace已于 2016 年过时,取而代之的是扩展事件。与trace相比,扩展事件的性能开销要小得多,可配置性也高得多。可以考虑使用扩展事件死锁事件来代替trace。

 

死锁扩展事件

从 SQL Server 2012 (11.x) 开始,在 SQL Trace 或 SQL Profiler 中应使用 xml_deadlock_report 扩展事件 (xEvent) 代替死锁图事件类。

 

同样从 SQL Server 2012 (11.x) 开始,当发生死锁时,system_health 会话已捕获包含死锁图的所有 xml_deadlock_report xEvent。由于默认启用了 system_health 会话,因此无需配置单独的 xEvent 会话来捕获死锁信息。使用 xml_deadlock_report xEvent 捕捉死锁信息不需要额外的操作。

 

捕获的死锁图通常有三个不同的节点:

·victim-list:死锁受害者进程标识符。

·进程列表:死锁涉及的所有进程的信息。

·资源列表:死锁涉及的资源信息。

打开 system_health 会话文件或环形缓冲区(ring buffer),如果记录了 xml_deadlock_report xEvent,Management Studio 就会以图形方式显示死锁涉及的任务和资源,如下例所示:

以下查询可查看 system_health 会话环形缓冲区捕获的所有死锁事件:

SELECT xdr.value('@timestamp', 'datetime') AS [Date],
    xdr.query('.') AS [Event_Data]
FROM (SELECT CAST([target_data] AS XML) AS Target_Data
            FROM sys.dm_xe_session_targets AS xt
            INNER JOIN sys.dm_xe_sessions AS xs ON xs.address = xt.event_session_address
            WHERE xs.name = N'system_health'
              AND xt.target_name = N'ring_buffer'
    ) AS XML_Data
CROSS APPLY Target_Data.nodes('RingBufferTarget/event[@name="xml_deadlock_report"]') AS XEventData(xdr)
ORDER BY [Date] DESC;

以下是输出结果集:

 

 

 

 

标签:事务,Server,会话,死锁,线程,SQL
From: https://www.cnblogs.com/abclife/p/18400039

相关文章

  • 【Geoserver使用】Geoserver 3前瞻
    文章目录前言一、GeoServer3CallforCrowdfunding(GeoServer3呼吁众筹)二、Geoserver3升级内容1.升级到3的几个原因2.Geoserver3的四个升级方向总结前言今天来看看最近Geoserver官方发布的关于Geoserver3重大升级众筹这篇官方博客中提到的几个升级方向。一......
  • 排它锁、共享锁与死锁的全面解析
    ‍前言在数据库技术中,封锁是实现并发控制的核心手段。它保证了多个事务同时进行时的数据一致性,避免了数据冲突和错误。对于初学者来说,理解封锁技术是迈向数据库高手的第一步。这篇文章将通过简洁明了的方式,帮助你轻松掌握封锁的相关知识。什么是封锁?为什么重要?封锁,顾......
  • PostgreSQL的walsender和walreceiver进程介绍
    PostgreSQL的walsender和walreceiver进程介绍在PostgreSQL中,WAL(Write-AheadLogging)是一种用于确保数据库事务日志安全可靠的机制。WAL是PostgreSQL进行数据库恢复、复制等操作的基础。walsender和walreceiver是PostgreSQL内部两个非常重要的进程,它们负责主......
  • Debian安装MySQL
    1.更新包sudoaptupdate2.安装MySQL的apt配置工具wgethttps://dev.mysql.com/get/mysql-apt-config_0.8.32-1_all.debaptinstallgnupgdpkg-imysql-apt-config_0.8.32-1_all.debaptupdate3.安装MySQL,中间会让设置密码sudoaptinstallmysql-server4.启动s......
  • mysql 常用知识点总结
    MySQL是一种广泛使用的关系型数据库管理系统(RDBMS),它基于结构化查询语言(SQL)。了解MySQL的语法对数据库管理和操作非常重要。以下是MySQL语法的详细完整解释,涵盖基本概念、创建表、查询、修改数据等内容。1.基础概念数据库(Database):数据库是存储数据的容器,里面可以包含......
  • Mysql数据库的原理和应用
    第一章数据库概述一学习环境介绍1.Windows10/11非家庭版内存8g2.Vmwareworkstation16.03.LAMP--LinuxAparchemysqlPHPLNMP--LinuxnginxmysqlPHPWAMP--WindowsAparchemysqlPHPWNMP--WindowsnginxmysqlPHP注意:Windows是非客服端操作系统,而是服务器版......
  • 中级练习[9]:Hive SQL
    目录1.查询相同时刻多地登陆的用户1.1题目需求1.2代码实现2. 销售额完成任务指标的商品2.1题目需求2.2代码实现及步骤3.根据商品销售情况进行商品分类3.1题目需求3.2代码实现1.查询相同时刻多地登陆的用户1.1题目需求从登录明细表(user_login_detail)中......
  • 中级练习[10]:Hive SQL
    目录1.各品类销量前三的所有商品1.1题目需求1.2代码实现2.各品类中商品价格的中位数2.1题目需求2.2代码实现3.找出销售额连续3天超过100的商品3.1题目需求3.2代码实现 1.各品类销量前三的所有商品1.1题目需求从订单详情表中(order_detail)和商品表(sku_......
  • MySQL8.0直方图详解
    1、什么是直方图MySQL8.0开始支持索引之外的数据分布统计信息可选项。它就是直方图(Histogram)。直方图通过估算查询谓词的选择率,以便选择合适的执行计划,也让SQL优化有了更多手段。在DB中,优化器负责将SQL转换为很多个不同的执行计划,然后从中选择一个最优的来实际执行。但是有时候优......
  • MySQL篇(运算符)(持续更新迭代)
    目录一、简介二、运算符使用1.算术运算符1.1.加法运算符1.2.减法运算符1.3.乘法与除法运算符1.4.求模(求余)运算符2.比较运算符2.1.等号运算符2.2.安全等于运算符2.3.不等于运算符2.4.空运算符2.5.非空运算符2.6.最小值运算符2.7.最大值运算符2.8.......