提到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. java程序的运行方式

    1.JAR File JAR 文件用于压缩和发布,而且还用于部署和封装库.组件和插件程序,并可被像编译器和 JVM 这样的工具直接使用 有点类似于net中的dll 2.Runnable JAR Fil ...

  2. redis.clients.jedis.exceptions.JedisDataException: WRONGTYPE Operation against a key holding the wrong kind of value

    错误原因: 因为redis中已经存在了相同的key, 而且key对应的值类型并不是Set,而是SortSet(改动前):再调用smembers时,抛出此错误. 解决方法: 将原来的的key给Del掉, ...

  3. HDU1561:The more, The Better(树形DP+01背包)

    Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物.但由于地理位置原因,有 ...

  4. 编译打包工具sbt的镜像设置

    sbt可以和maven共用一个镜像,公司内部有的自然最后不过 创建文件:~/.sbt/repositories [repositories] local aliyun: http://maven.al ...

  5. MySQL 用户管理及权限管理

    MySQL 默认有个root用户,但是这个用户权限太大,一般只在管理数据库时候才用.如果在项目中要连接 MySQL 数据库,则建议新建一个权限较小的用户来连接. 在 MySQL 命令行模式下输入如下命 ...

  6. OpenCV学习(34) 点到轮廓的距离

    在OpenCV中,可以很方便的计算一个像素点到轮廓的距离,计算距离的函数为: double pointPolygonTest(InputArray contour, Point2f pt, bool ...

  7. C++11 lambda 表达式解析

    C++11 新增了很多特性,lambda 表达式是其中之一,如果你想了解的 C++11 完整特性,建议去这里,这里,这里,还有这里看看.本文作为 5 月的最后一篇博客,将介绍 C++11 的 lamb ...

  8. cocos2dx游戏存储举例及其注意事项

    今天白白跟大家分享一下cocos2dx中游戏的存储及需要注意的事项 cocos2dx中自带了存储类:CCUserDefault ,倘若需要存储的数据量教大的话,建议使用数据库来存储 现在先给大家看一下 ...

  9. Linux:su和su-的区别

    大部分Linux发行版的默认账户是普通用户,而更改系统文件或者执行某些命令,需要root身份才能进行,这就需要从当前用户切换到root用户.Linux中切换用户的命令是su或su -. 如上图所示,一 ...

  10. Android实现固定头部信息,挤压动画(相似通讯录)

    半年前,那时候我还是个大四的学生,每天都在找工作度过,想去北京体验一下蚁族生活,奋然离开了济南,哎...在济南我们学校还是数得着的好学校,去了北京就什么都不是了,一切的辛酸仅仅有自己知道,那时候的我仅 ...