SQL Server里如何处理死锁
在今天的文章里,我想谈下SQL Server里如何处理死锁。当2个查询彼此等待时会发生死锁,没有一个查询可以继续它们的操作。首先我想给你大致讲下SQL Server如何处理死锁。最后我会展示下SQL Sever里特定的死锁类型,还有你如何避免和解决它们。
死锁处理
死锁的好处是SQL Server自动检测并解决它们。为了解决死锁,SQL Server需要回滚2个事务中最便宜的那个。在SQL Server上下文中,最便宜的事务是写入事务日志更少字节的那个。
SQL Server在后台进程中实现死锁检测称为死锁监控(Deadlock Monitor)。这个后台进程每5秒钟运行一次,为死锁检查当前锁定情况。在最坏的情况中,因此一个死锁不应该超过5秒。这个查询会回滚并收到1205错误号。死锁的好事是你可以完整从错误情况下还原,不需要用户的任何干预。一个聪明的开发者必须按下列步骤来从死锁中恢复:
- 当异常抛出时,检查1205错误号
- 暂时停止程序,给其他查询时间来完成它的事务并释放它获得的锁
- 重新提交查询,即被SQL Server回滚的。
重新提交查询后,这个查询应该继续执行,没有任何问题,因为其它查询已经完成它的事务。当然你应该保持再次发生死锁的跟踪,这样的话,你不用反复重试你的事务。
你可以用多种方法来故障排除死锁。SQL Server Profiler提供Deadlock Graph事件,一旦死锁检测到就会发生。如果你在SQL Server 2008或更高,你可以使用故障排除来故障排除死锁场景。扩展事件提供你system_health事件会话,它跟踪自SQL Server上次重启后发生过的死锁。还有启用1222跟踪标记,SQL Server会把死锁信息写入错误日志。
死锁类型
在SQL Server里会发生各种类型的死锁。在这一部分我想进一步谈下最常见的几个。
几乎每个SQL Server我看到最典型的的死锁是著名的书签查找死锁,当你有同时对聚集和非聚集索引读写活动时发生。它基本上是因为不好的索引设计造成的。在我作日常SQL Server的故障排除重,我可以说所有的死锁,至少有90%可以通过更好的索引设计来解决。书签查找死锁可以通过提供覆盖非聚集索引轻松解决。
另一个常见的死锁是所谓的循环死锁(Cycle Deadlock),这里你的每个查询用不同的顺序访问表。为了避免这个特定的死锁,你要确保每个查询用同样的顺序访问表。在SQL Server里会发生的最有意思的死锁是所谓的内部并行死锁(Intra-Parallelism Deadlock),这里平行的运算符在各自的线程内部死锁。下图展示了一个典型死锁图。

图片本身就是一个艺术品,它因触发SQL Server里的BUG而发生。遗憾的是,这个BUG不会被微软修正,因为它引入回归的可能性。因此你要确保引起这个死锁的查询,要在SQL Server里单线程运行。你可以通过多个选项来实现单线程执行:
- 在你的索引策略上下功夫,这样的话查询的花费会在当前并行阈值下(默认为5)
- 使用MAXDOP 1查询提示,来提示SQL Server以单线程运行你的问题查询
另一个死锁的特效疗法是启用乐观并发,尤其是提交读快照隔离(Read Committed Snapshot Isolation (RCSI)),他对你的程序是完全透明的。使用乐观并发,共享锁消失,这意味着在SQL Server里你可以避免大量的典型锁。
小结
死锁是SQL Server通过回滚最便宜的事务自动处理。然而你要尽可能小的确保死锁,因为每个回滚的死锁都会给你的终端用户带来不好的影响。死锁可以通过好的索引策略来避免,另外使用乐观并发也是应付它们的特效药。
感谢关注!
原文链接
https://www.sqlpassion.at/archive/2017/02/20/how-to-handle-deadlocks-in-sql-server
SQL Server里如何处理死锁的更多相关文章
- 在SQL Server里如何处理死锁
在今天的文章里,我想谈下SQL Server里如何处理死锁.当2个查询彼此等待时会发生死锁,没有一个查询可以继续它们的操作.首先我想给你大致讲下SQL Server如何处理死锁.最后我会展示下SQL ...
- SQL Server里如何处理死锁 (转)
http://www.cnblogs.com/woodytu/p/6437049.html 在今天的文章里,我想谈下SQL Server里如何处理死锁.当2个查询彼此等待时会发生死锁,没有一个查询可以 ...
- SQL Server里因丢失索引造成的死锁
在今天的文章里我想演示下SQL Server里在表上丢失索引如何引起死锁(deadlock)的.为了准备测试场景,下列代码会创建2个表,然后2个表都插入4条记录. -- Create a table ...
- SQL Server里的文件和文件组
在今天的文章里,我想谈下SQL Server里非常重要的话题:SQL Server如何处理文件的文件组.当你用CREATE DATABASE命令创建一个简单的数据库时,SQL Server为你创建2个 ...
- SQL Server里的闩锁介绍
在今天的文章里我想谈下SQL Server使用的更高级的,轻量级的同步对象:闩锁(Latch).闩锁是SQL Server存储引擎使用轻量级同步对象,用来保护多线程访问内存内结构.文章的第1部分我会介 ...
- 在SQL Server里为什么我们需要更新锁
今天我想讲解一个特别的问题,在我每次讲解SQL Server里的锁和阻塞(Locking & Blocking)都会碰到的问题:在SQL Server里,为什么我们需要更新锁?在我们讲解具体需 ...
- SQL Server中解决死锁
SQL Server中解决死锁的新方法介绍 数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过SQL Server 2005, 现在似乎有了一种新的解决办法. 将下面的 ...
- sql server 里的文件和文件组使用
转自:https://www.cnblogs.com/woodytu/p/5821827.html 参考:https://www.sqlskills.com/blogs/paul/files-and- ...
- SQL Server中解决死锁的新方法介绍
SQL Server中解决死锁的新方法介绍 数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过SQL Server 2005, 现在似乎有了一种新的解决办法. 将下面的 ...
随机推荐
- scrapy选择器归纳
python 爬虫: srcrapy框架xpath和css选择器语法 Xpath基本语法 一.常用的路径表达式: 表达式 描述 实例 nodename 选取nodename节点的所有子节点 //div ...
- 对Promise的一些深入了解
1.介绍promise和模仿Promise.all和Promise.race promise的设计主要是解决回调地狱(接收结果用回调函数来处理,但必须传入回调函数)的问题,由一层层嵌套回调函数改为由t ...
- Linux内核中Makefile、Kconfig和.config的关系(转)
我们在编译Linux内核时,往往在Linux内核的顶层目录会执行一些命令,这里我以RK3288举例,比如:make firefly-rk3288-linux_defconfig.make menuco ...
- [OC] 杂项
使用JSONModel的一个好处是,可以防止 [数据是NSNULL的时候,OC无法直接通过if(XX)来判空 ]引起的错误. 字符串与字符串对比不要使用 str1 != str2 这种写法,而用 ![ ...
- Codeforces.97D.Robot in Basement(bitset 模拟)
题目链接 (ozr attack) 考虑怎么暴力,就是先在所有非障碍格子上全放上机器人,然后枚举每一步,枚举每个机器人移动这一步,直到所有机器人都在出口位置.复杂度是\(O(nmk)\)的. 怎么优化 ...
- 冲刺NOIP复习,算法知识点总结
前言 离NOIP还有一个星期,匆忙的把整理的算法补充完善,看着当时的整理觉得那时还年少.第二页贴了几张从贴吧里找来的图片,看着就很热血的.当年来学这个竞赛就是为了兴趣,感受计算机之美的. ...
- BZOJ2491 : Quelling Blade
首先将合成树展开,得到一棵不超过$m(m\leq 10^6)$的有根树. 问题等价于,不休息地访问所有点,访问每个点需要时间$t_i$,价值为$v_i$. 设$vis_i$为访问$i$点的时间(不含$ ...
- python正则表达式(一)
---恢复内容开始--- 正则表达式,又称正规表示式.正规表示法.正规表达式.规则表达式.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE),是计 ...
- BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP
题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...
- Flask对象配置
Flask的配置就是在 app.config 中添加一个键值对,但是你存进去的键必须是config中应该存在的,如果不再存在的话,它会默认无用,就这么放着 config中有用的key { 'DEBUG ...