iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >SQLSERVER语句交错引发的死锁问题怎么解决
  • 300
分享到

SQLSERVER语句交错引发的死锁问题怎么解决

sqlserver 2023-03-01 18:03:03 300人浏览 薄情痞子
摘要

这篇文章主要讲解了“sqlSERVER语句交错引发的死锁问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SQLSERVER语句交错引发的死锁问题怎

这篇文章主要讲解了“sqlSERVER语句交错引发的死问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SQLSERVER语句交错引发的死锁问题怎么解决”吧!

    一:背景

    1. 讲故事

    相信大家在使用 SQLSERVER 的过程中经常会遇到 阻塞死锁,尤其是 死锁,比如下面的输出:

    (1 row affected) Msg 1205, Level 13, State 51, Line 5 Transaction (Process ID 62) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

    二:死锁简析

    1. 一个测试案例

    开启两个会话 6566 ,分别使用如下查询。

    -- 会话 65 --
    BEGIN TRAN
    UPDATE dbo.Employees SET Title='Dr.' WHERE EmployeeID=1;
    WaiTFOR DELAY '00:00:10'
    SELECT * FROM dbo.Orders WHERE OrderID=10258
    ROLLBACK
    
    -- 会话 66 --
    BEGIN TRAN
    UPDATE  dbo.Orders SET  ShipAddress='上海' WHERE OrderID=10258
    WAITFOR DELAY '00:00:10'
    SELECT * FROM dbo.Employees WHERE EmployeeID=1;
    ROLLBACK

    两个会话非常简单,交错的对 EmployeesOrders 进行 SELECT 和 UPDATE 操作,稍等几秒后就会出现死锁。

    SQLSERVER语句交错引发的死锁问题怎么解决

    2. 寻找死锁源头

    当我们的应用程序拿到了这样的输出其实作用是不大的,要想溯源最好就是通过不断的对 SQLSERVER 进行监视来捕获死锁时的上下文信息,手段也有很多:

    这里我们就用第一种方式,一定要勾选 TextData 项,因为这里面会有死锁上下文信息的xml表示,截图如下:

    SQLSERVER语句交错引发的死锁问题怎么解决

    将 profile 开启后,重新执行刚才的两个查询,一旦出现死锁,profile 就会成功捕获,然后 copy 出 TextData 项,截图如下:

    SQLSERVER语句交错引发的死锁问题怎么解决

    <deadlock-list>
     <deadlock victim="process2d69c9748c8">
      <process-list>
       <process id="process2d69c9748c8" taskpriority="0" logused="324" waitresource="KEY: 7:72057594043170816 (8194443284a0)" waittime="1304" ownerId="70740" transactionname="user_transaction" lasttranstarted="2023-02-19T22:11:26.413" XDES="0x2d6a0200428" lockMode="S" schedulerid="5" kpid="13816" status="suspended" spid="66" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2023-02-19T22:11:26.413" lastbatchcompleted="2023-02-19T22:11:26.410" lastattention="1900-01-01T00:00:00.410" clientapp="Microsoft SQL Server Management Studio - Query" hostname="DESKTOP-STS8TPB" hostpid="1696" loginname="DESKTOP-STS8TPB\Administrator" isolationlevel="read committed (2)" xactid="70740" currentdb="7" currentdbname="Northwind" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
        <executionStack>
         <frame procname="adhoc" line="5" stmtstart="24" stmtend="128" sqlhandle="0x020000007383D935b349bc173c0f104de14945e9a526322b0000000000000000000000000000000000000000">
    unknown     </frame>
         <frame procname="adhoc" line="5" stmtstart="204" stmtend="294" sqlhandle="0x020000002c3b203105961d63d10b17e54ed6ac081105f9450000000000000000000000000000000000000000">
    unknown     </frame>
        </executionStack>
        <inputbuf>
    
    BEGIN TRAN
    UPDATE  dbo.Orders SET  ShipAddress=&apos;上海&apos; WHERE OrderID=10258
    WAITFOR DELAY &apos;00:00:10&apos;
    SELECT * FROM dbo.Employees WHERE EmployeeID=1;
    ROLLBACK
        </inputbuf>
       </process>
       <process id="process2d6ae694ca8" taskpriority="0" logused="368" waitresource="KEY: 7:72057594044088320 (59ce0997f9b8)" waittime="3468" ownerId="70716" transactionname="user_transaction" lasttranstarted="2023-02-19T22:11:24.247" XDES="0x2d6a7284428" lockMode="S" schedulerid="9" kpid="7124" status="suspended" spid="65" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2023-02-19T22:11:24.247" lastbatchcompleted="2023-02-19T22:11:24.247" lastattention="1900-01-01T00:00:00.247" clientapp="Microsoft SQL Server Management Studio - Query" hostname="DESKTOP-STS8TPB" hostpid="1696" loginname="DESKTOP-STS8TPB\Administrator" isolationlevel="read committed (2)" xactid="70716" currentdb="7" currentdbname="Northwind" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
        <executionStack>
         <frame procname="adhoc" line="5" stmtstart="26" stmtend="118" sqlhandle="0x02000000dd7720067e0519b8a368501716c04b4b50cfe6be0000000000000000000000000000000000000000">
    unknown     </frame>
         <frame procname="adhoc" line="5" stmtstart="196" stmtend="282" sqlhandle="0x0200000093f01512208755a056f5f28930fbd3dedf58a2850000000000000000000000000000000000000000">
    unknown     </frame>
        </executionStack>
        <inputbuf>
    
    BEGIN TRAN
    UPDATE dbo.Employees SET Title=&apos;Dr.&apos; WHERE EmployeeID=1;
    WAITFOR DELAY &apos;00:00:10&apos;
    SELECT * FROM dbo.Orders WHERE OrderID=10258
    ROLLBACK
        </inputbuf>
       </process>
      </process-list>
      <resource-list>
       <keylock hobtid="72057594043170816" dbid="7" objectname="Northwind.dbo.Employees" indexname="PK_Employees" id="lock2d69ccbbb80" mode="X" associatedObjectId="72057594043170816">
        <owner-list>
         <owner id="process2d6ae694ca8" mode="X"/>
        </owner-list>
        <waiter-list>
         <waiter id="process2d69c9748c8" mode="S" requestType="wait"/>
        </waiter-list>
       </keylock>
       <keylock hobtid="72057594044088320" dbid="7" objectname="Northwind.dbo.Orders" indexname="PK_Orders" id="lock2d69ccbbf80" mode="X" associatedObjectId="72057594044088320">
        <owner-list>
         <owner id="process2d69c9748c8" mode="X"/>
        </owner-list>
        <waiter-list>
         <waiter id="process2d6ae694ca8" mode="S" requestType="wait"/>
        </waiter-list>
       </keylock>
      </resource-list>
     </deadlock>
    </deadlock-list>

    虽然上面有图形化表示,但在生产环境下参考价值并不多,因为这张图蕴含的信息比较少,熟读和整理 xml 的内容就非常必要了,截图如下:

    SQLSERVER语句交错引发的死锁问题怎么解决

    仔细观察上面的这张图可以清晰的看到,spid=66 持有了 Orders.PK_Orders 索引上哈希码为 59ce0997f9b8 键值的 X 锁,之后需要再次获取 Employees.PK_Employees 索引上哈希码为 8194443284a0 键值上的 S 锁,很不巧的是,此时的 Employees.PK_Employees 索引上哈希码为 8194443284a0 的键值已经被 spid=65 的会话附加了 X 锁,这是一种典型的相互等待造成的死锁。

    同时也可以观察到,我们的语句是一个 adhoc 即时查询,其外层也没有 存储过程 之类的包围语句。

    3. 寻找解决方案

    知道了是什么语句和什么语句之间的冲突之后,后面的问题就比较简单了,常见措施如下:

    使用 nolock 脏读

    由于冲突中涉及到了 S 锁,其实绝大多数系统对脏读不是特别敏感,所以使用 nolock 无锁提示是一个好办法。

    BEGIN TRAN
    UPDATE  dbo.Orders SET  ShipAddress='上海' WHERE OrderID=10258
    WAITFOR DELAY '00:00:10'
    SELECT * FROM dbo.Employees WITH(NOLOCK) WHERE EmployeeID=1;
    ROLLBACK
    
    
    BEGIN TRAN
    UPDATE dbo.Employees SET Title='Dr.' WHERE EmployeeID=1;
    WAITFOR DELAY '00:00:10'
    SELECT * FROM dbo.Orders WITH(NOLOCK) WHERE OrderID=10258
    ROLLBACK

    使用 mvcC 多版本控制

    现代化的关系型数据库都支持 快照读 来解决 并发读写 的冲突,同时又能保证不脏读,简而言之就是在事务修改时将修改前的数据存到 tempdb 中来形成字段的版本化。

    首先需要从 数据库 级别开启它。

    ALTER DATABASE Northwind SET ALLOW_SNAPSHOT_ISOLATION ON

    然后在各自事务中显式使用 SNAPSHOT 隔离级别查询,参考sql如下:

    -- 会话 65 --
    SET TRAN ISOLATION LEVEL SNAPSHOT
    BEGIN TRAN
    UPDATE dbo.Employees SET Title='Dr.' WHERE EmployeeID=1;
    WAITFOR DELAY '00:00:10'
    SELECT * FROM dbo.Orders WHERE OrderID=10258
    ROLLBACK
    
    -- 会话 66 --
    SET TRAN ISOLATION LEVEL SNAPSHOT
    BEGIN TRAN
    UPDATE  dbo.Orders SET  ShipAddress='上海' WHERE OrderID=10258
    WAITFOR DELAY '00:00:10'
    SELECT * FROM dbo.Employees  WHERE EmployeeID=1;
    ROLLBACK

    感谢各位的阅读,以上就是“SQLSERVER语句交错引发的死锁问题怎么解决”的内容了,经过本文的学习后,相信大家对SQLSERVER语句交错引发的死锁问题怎么解决这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

    您可能感兴趣的文档:

    --结束END--

    本文标题: SQLSERVER语句交错引发的死锁问题怎么解决

    本文链接: https://www.lsjlt.com/news/198103.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • SQLSERVER语句交错引发的死锁问题怎么解决
      这篇文章主要讲解了“SQLSERVER语句交错引发的死锁问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SQLSERVER语句交错引发的死锁问题怎...
      99+
      2023-03-01
      sqlserver
    • SQLSERVER 语句交错引发的死锁问题案例详解
      目录一:背景1. 讲故事二:死锁简析1. 一个测试案例2. 寻找死锁源头3. 寻找解决方案三:总结一:背景 1. 讲故事 相信大家在使用 SQLSERVER 的过程中经常会遇到 阻塞 和 死锁,尤其是 死锁,比如下面的输...
      99+
      2023-02-21
      sqlserver语句交错引发的死锁 sqlserver死锁
    • SQLSERVER语句交错引发的死锁问题案例详解
      目录一:背景1. 讲故事二:死锁简析1. 一个测试案例2. 寻找死锁源头3. 寻找解决方案三:总结一:背景 1. 讲故事 相信大家在使用 SQLSERVER 的过程中经常会遇到 阻塞...
      99+
      2023-02-21
      sqlserver语句交错引发的死锁 sqlserver死锁
    • sqlserver死锁问题怎么解决
      在SQL Server中解决死锁问题通常需要以下步骤: 监控死锁:使用SQL Server Profiler或Extended ...
      99+
      2024-05-11
      sqlserver
    • sql死锁问题怎么解决
      本篇内容介绍了“sql死锁问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! --查询锁表信息,...
      99+
      2024-04-02
    • 一条sql语句所引发的问题怎么解决
      这篇文章主要介绍“一条sql语句所引发的问题怎么解决”,在日常操作中,相信很多人在一条sql语句所引发的问题怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”一条sql语...
      99+
      2023-01-31
      sql
    • Java死锁问题怎么解决
      今天小编给大家分享一下Java死锁问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。前言:死锁(Dead Lock)...
      99+
      2023-06-30
    • Go 语言中的死锁问题解决
      目录死锁如何避免死锁死锁代码死锁 死锁的4个条件 不可剥夺 线程已经获得的资源,在未使用完之前,不能被其他线程剥夺,只能在使用完后自己释放。 请求保持 线程...
      99+
      2024-04-02
    • C语言多线程开发中死锁与读写锁问题怎么解决
      今天小编给大家分享一下C语言多线程开发中死锁与读写锁问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。死锁有时,一个...
      99+
      2023-06-30
    • 如何解决Go语言中的死锁问题?
      如何解决Go语言中的死锁问题?Go语言具有并发编程的特性,可以通过使用goroutine和channel来实现并发操作。然而,在并发编程中,死锁是一个常见的问题。当goroutine之间相互依赖于彼此的资源,并且在访问这些资源时产生了循环依...
      99+
      2023-10-22
      解决方案 Go语言 死锁
    • MongoDB怎么检测和解决死锁问题
      在MongoDB中,死锁问题通常是由于并发操作导致的,解决死锁问题通常需要对数据库的设计和应用程序的并发控制进行优化。 以下是一些检...
      99+
      2024-04-19
      MongoDB
    • Java多线程死锁问题怎么解决
      解决Java多线程死锁问题的常用方法有以下几种:1. 避免使用多个锁:尽量减少使用多个锁来降低出现死锁的概率。2. 按照固定的顺序获...
      99+
      2023-09-22
      Java
    • C语言数组越界引发的死循环问题解决
      目录一、引入二、代码缺陷三、为什么会死循环?四、补充说明五、总结一、引入 下面的程序在VS编译器会出现什么问题?运行结果是什么?为什么? #include <stdio.h&g...
      99+
      2022-11-13
      C语言 数组越界
    • Go语言死锁与goroutine泄露问题的解决
      目录什么时候会导致死锁 发送单个值时的死锁 多个值发送的死锁 解决多值发送死锁 应该先发送还是先接收 goroutine 泄漏 如何发现泄露 小结 什么时候会导致死锁 在计算机组成...
      99+
      2024-04-02
    • Java线程技术中的死锁问题怎么解决
      这篇文章主要介绍“Java线程技术中的死锁问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java线程技术中的死锁问题怎么解决”文章能帮助大家解决问题。我们知道,使用 synchroniz...
      99+
      2023-06-02
    • 高并发状态下ReplaceInto造成的死锁问题解决
      目录1.问题出现:2.分析解决3.解决方案:1.问题出现: 在测试阶段,大数据并发的情况下,发现sql语句造成表的死锁,过一段时间,死锁消失。于是进行排查 报错如下: 对应的sql...
      99+
      2023-01-18
      Replace Into死锁 Replace Into
    • C++ 函数如何解决并发编程中的死锁问题?
      在 c++++ 中,使用互斥量函数可以解决多线程并发编程中的死锁问题。具体步骤如下:创建一个互斥量;当线程需要访问共享变量时,获得互斥量;修改共享变量;释放互斥量。这样可以确保任何时刻只...
      99+
      2024-04-26
      并发编程 死锁 c++
    • 高并发状态下Replace Into造成的死锁问题解决
      目录1.问题出现:2.分析解决3.解决方案:1.问题出现: 在测试阶段,大数据并发的情况下,发现sql语句造成表的死锁,过一段时间,死锁消失。于是进行排查 报错如下: 对应的sql语句如下: @Insert("...
      99+
      2023-01-18
      ReplaceInto死锁 ReplaceInto
    • MySQL优化index merge引起的死锁怎么解决
      本篇内容介绍了“MySQL优化index merge引起的死锁怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!背景生产环境出...
      99+
      2023-06-30
    • 怎么解决ubuntu12.04卡死的问题
      这篇文章主要介绍“怎么解决ubuntu12.04卡死的问题”,在日常操作中,相信很多人在怎么解决ubuntu12.04卡死的问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么解决ubuntu12.04卡死...
      99+
      2023-06-13
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作