提到sql server,想必最让人头疼的当属锁机制了。在默认的read committed隔离模式下,连最基本的select操作都要申请各种粒度的锁,而且在读取数据过程中会不断有锁升级、转化。在非未提交读的隔离级别中,一个select操作会对每一条读到的记录或键值加S锁(何时释放还要视记录是否返回以及隔离级别而定),对每一条用到的Index上的键值加S锁,对读过的每个page和table上加IS锁...update、insert、delete操作申请锁的量和复杂度就更大了。
死锁和阻塞都是sql server要实现事务隔离的产物。有时候在同一个表上的事务隔离,并发度高一点会发生死锁;并发度低一点发生的是阻塞。所以死锁的问题定位和解决与阻塞有想通的地方,解决死锁最关键的就是要找到死锁双方或多方共同争抢的资源是哪个。下面分享一个最近碰到的真实生产环境上的案例,解析死锁抓取以及解决过程。
 
某外资物流公司
操作系统:Windows Server 2012 Enterprise x64
数据库   :SQL Server 2014 Enterprise X64
数据量   :300GB左右日常事务并发量比较高
现状        :由于一个业务sp的大量并行运行导致死锁,死锁发生一方作为牺牲资源后回滚过程很漫长导致重要业务表被锁,业务中断
解决排查过程:
首先必须找到死锁资源:
1)通过SQL Server Profiler新建一个trace,事件选择可以精简点便于我们观察死锁,选择“Locks”事件
下的Lock:Deadlock和Deadlock graph即可,trace文件大小设置为100M上限以便分析
2)一段时间后停止抓取,很直观看到死锁一直出现,且点开所有deadlock graph得到死锁图形分析,死锁都是发生在同一资源上:

到这一步为止我们只是能确认死锁发生了,而且发生在同一资源上,还没能获取具体的死锁语句和资源信息,问题还不能得到根本解决。

 
3)为了查看死锁信息,数据库引擎提供了监视工具:跟踪标识(1222)。打开这个跟踪开关,所有获取的死锁信息会写到SQL Server的错误日志中供我们进一步分析。这一步打开这个开关,在SSMS中运行
DBCC TRACEON(1222,-1);
 
4)从trace的死锁图形看死锁发生很频繁,为了不让日志增长过大,过2至3分钟后将开关关掉。在SSMS中运行
DBCC TRACEOFF(1222,-1),这一步很重要;
 
5)打开SQL Server errorlog,找到死锁输出信息,这个输出内容很丰富而且比较复杂,这里只把我们所需的几个重要点挑出来

死锁信息始于 deadlock-list关键字(倒着看),deadlock victim显示死锁的牺牲方,process id显示进程id号,由于截图没那么齐全,还包含很多死锁信息,比如可以查看进程spid号,事务隔离级别,当前正进行的批处理操作,当前正在运行的语句,申请中的资源等等。

通过对错误日志的分析得到死锁批处理和死锁语句:exec usp_obal_import_so,查到死锁语句:delete from t_po_detail where po_number in(select po_number from t_so_po where so_number=@v_vchSOID and whid=@v_vchWHID) and whid=@v_vchWHID,这是usp_obal_import_so中的一段语句,锁资源:表tbl_po_detail_generic(用户脚本定时执行获得) ,但是这个sp的执行根本不会操作tbl_po_detail_generic ,是不是哪里出问题了呢?
       6)我们可以在SSMS中看看这条语句的执行计划,运行语句之前在SSMS中运行
     set statistics profile on或者在“查询”子菜单中选择“包括实际的执行计划”,我们用第二种更直观,如下

很明显在执行计划中可以看到tbl_po_detail_generic有个全表扫描操作,再与t_po_detail表做hash连接。全表扫描导致每次语句执行会获取该表的表锁,深究原因发现tbl_po_detail_generic的外键约束导致每次删除t_po_detail数据会操作tbl_po_detail_generic表。

       7)到这里剖析死锁工作基本结束,后面解决方法有两种:一是根据执行计划在tbl_po_detail_generic建立适当索引避免表扫描;二是如果业务逻辑许可,删掉外键约束。
总结:
       要真正做到从源头上降低死锁发生几率,还是要从程式本身做好。如果不能去修改程式,可以考虑从另外几个方面消除死锁:

1 调整索引来调整执行计划,减少锁的申请数目;

2 使用'nolock'参数,让SELECT语句不要申请S锁,减少锁申请数目

3 升级锁粒度,将死锁转化成阻塞问题

4 使用快照隔离级别SNAPSHOT LEVEL

 

SQL Server死锁排查经历 -基于SqlProfiler的更多相关文章

  1. SQL Server死锁排查

    1. 死锁原理 根据操作系统中的定义:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态. 死锁的四个必要条件:互斥条件(Mutua ...

  2. sql server 死锁排查

    记得以前客户在使用软件时,有偶发出现死锁问题,因为发生的时间不确定,不好做问题的重现,当时解决问题有点棘手了. 现总结下查看死锁的常用二种方式: 第一种是图形化监听: sqlserver --> ...

  3. SQL Server死锁

    SQL Server死锁 多个事务之间互相等待对方的资源,导致这些事务永久等待 注意是永久等待,而非长事务 死锁的4个条件 互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程 ...

  4. SQL Server的镜像是基于物理块变化的复制 镜像Failover之后数据的预热问题

    SQL Server的镜像是基于物理块变化的复制 镜像Failover之后数据的预热问题 基于物理块变化的复制,没有并行也是很快的. 逻辑复制的日志是按事务结束的时间排序的,而物理复制是与事务无关的, ...

  5. SQL Server死锁的解除方法

    如果想要查出SQL Server死锁的原因,下面就教您SQL Server死锁监控的语句写法,如果您对此方面感兴趣的话,不妨一看. 下面的SQL语句运行之后,便可以查找出SQLServer死锁和阻塞的 ...

  6. Update导致SQL Server死锁的典型方法(转载)

    此文为转载文章,描述的很好,没有验证过. 最近遇到了一个看上去很奇怪,分析起来很有意思的死锁问题.这个死锁看上去难以理解.而分析过程中,又使用了很多分析SQL Server死锁的典型方法.记录下来整个 ...

  7. Sql Server性能排查和优化懒人攻略

    转载自作者zhang502219048的微信公众号[SQL数据库编程]:Sql Server性能排查和优化懒人攻略 很多年前,笔者那时刚从广东技术师范学院(现为广东技术师范大学,以前为广东民族学院)的 ...

  8. SQL Server死锁总结

    1. 死锁原理 根据操作系统中的定义:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态. 死锁的四个必要条件:互斥条件(Mutua ...

  9. SQL Server死锁总结 [转]

    1. 死锁原理 根据操作系统中的定义:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态. 死锁的四个必要条件:互斥条件(Mutua ...

随机推荐

  1. 算法:冒泡排序(Bubble Sort)、插入排序(Insertion Sort)和选择排序(Selection Sort)总结

    背景 这两天温习了 5 中排序算法,之前也都看过它们的实现,因为没有深入分析的缘故,一直记不住谁是谁,本文就记录一下我学习的一些心得. 三种排序算法可以总结为如下: 都将数组分为已排序部分和未排序部分 ...

  2. 构建一个高可扩展性javabean和jsp连接数据库操作

    1. 我们先在Tomcat 中创建一个DataSource- jdbc/Panabia,然后再创建一个java“基类”,这个类封装了数据库连接和连接的释放. package Panabia.db; i ...

  3. 配置quartz数据源的三种方式

    如果是使用了JDBC JobStore或JobStoreCMT获得持久的Job时,就要配置相关的数据源了. 方式一:使用quartz.properties文件,这时只需要在property文件中增加如 ...

  4. AIX加入�能够telnet远程连接账号方法

    AIX 中加入�账号能够使用命令mkuser 和 SMIT 两种方式,这里介绍SMIT方式 1.使用root 账号登录AIX 2.输入 smitty user 3.选择Add a User 4.输入& ...

  5. sql递归查询子级

    WITH T(emp_no, name, dept_no, the_level, path,path1,manager_id) AS( SELECT emp_no, name, dept_no ,1 ...

  6. DB-library 常用函数

    以下转自:http://blog.csdn.net/lwbeyond/article/details/5620801 1. Dbcmd和dbfcmd 函数原形: Dbcmd(DBPROCESS *pr ...

  7. C++ Explicit Constructors(显式构造函数)

    C++ 为类(Class)提供了许多默认函数.如果自己没有申明,编译器会为我们提供一个copy构造函数.一个copy assignment操作符和一个析构函数.此外,如果没有申明任何构造函数,编译器会 ...

  8. 关于json与protobuf的材料

    1. https://solicomo.com/network-dev/protobuf-proto3-vs-proto2.html 2.

  9. spring boot xml与dao 映射关系

    mybatis的xml路径要和 dao的路径一模一样 dao 用@Mapper 注解

  10. IE11下javascript报堆栈溢出问题的解决

    在IE11浏览器下,使用日期函数里面的toLocaleDateString()会报堆栈溢出 不知道是不是跟我的其他相关代码有关,还是就是这个toLocaleDateString()在IE11确实不太一 ...