什么是死锁?如何捕获死锁信息?如何避免死锁?

0
已邀请:
2

gogodiy - 天善智能数据库专家、Tableau爱好者 2013-07-12 回答

死锁(deadlock)是一种特殊的阻塞情况——两个对话互相阻塞。每个对话在保留自己的资源的同时,试图访问其他对话锁定的资源。这将导致一种循环阻塞的情境,也被称为抱死(deadly embrace)。
当两个进程试图在相同的资源上升级其锁机制时死锁也频繁出现。
SQL Server有一个死锁侦测进程,称为锁监视器(lock monitor),定期检查SQL Server中死锁的存在。一旦侦测到死锁条件,选择涉及死锁的一个会话作为受害者以打断循环阻塞。这个过程包括撤销受害者进程保留的所有资源,通过回滚被选为受害者的会话的未提交事务来做到这一点。
SQL Server通过评估撤销参与会话的事务的代价来确定作为死锁受害者的会话,并选择代价最小的一个。
SET DEADLOCK_PRIORITY LOW
SET DEADLOCK_PRIORITY NORMAL --默认设置

当SQL Server选择一个会话作为受害者时,它发起一个带有错误号的错误。SQL Server使用TRY/CATCH结构来处理错误。SQL SEerver自动回滚受害者会话的事务来保证数据库的一致性。这个回滚确保会话回到事务开始前的相同状态。
TRY/CATCH方式捕捉错误,使用ERROR_NUMBER()函数检查错误号是否有死锁。一旦确定了死锁,可以尝试重启事务设定的次数。

收集死锁信息:
通过Profiler工具使用特殊的跟踪事件,设置跟踪标志1222和1204:
跟踪标志1222提供了关于死锁最详细的信息,将收集到的信息写入到死锁事件发生的服务器上的日志文件中,按照自愿和进程排序信息,并提高更多的信息。
跟踪标志1204提供帮助分析死锁起因的详细信息,它按照死锁涉及的节点排序这些信息。
DBCC TRACEON语句用于打开(或启用)跟踪标志。使用DECC TRACEOFF语句禁用它,使用DBCC TRACESTATUS语句确定跟踪标志的状态。
启用:
DBCC TRACEON (1222,-1)
DBCC TRACEON (1204,-1)
禁用:
DBCC TRACEOFF (1222,-1)
DBCC TRACEOFF (1204,-1)
查询状态:
DBCC TRACESTATUS
分析死锁:
操作步骤:
1. 在SSMS界面中使用DBCC TRACEON设置跟踪标志;
2. 打开SQL Profiler,选择Locks:Deadlock graph事件跟踪死锁;
3. 在TextData字段显示死锁XML信息,并在下方显示死锁图表;

避免死锁
 按照相同的时间顺序访问资源
 减少锁
 最小化锁争用

按照相同的时间顺序访问资源:
最常用的是确保每个事务按照相同的物理顺序访问资源。
减少被访问资源的数量:
使用SQL Server特性:
 将非聚集索引转换为聚集索引
因为非聚集索引的叶子页面与堆或聚集索引的数据页面分离,因此需要两个锁:一个用于基本表(聚集或堆),另一个用于非聚集索引。而聚集索引的叶子页面等于表的数据页面,因此只需要一个锁。和非聚集索引相比,减少了同一个查询访问的资源数量。
 为SELECT语句使用覆盖索引
覆盖索引类似表的“复制”机制,SELECT语句可以通过覆盖索引获得需要的数据,而不再另外访问基本表。这样基本表可以被其他会话锁定。
最小化锁的争用:
可以通过避免在一个争用的资源上请求锁资源来解决死锁问题。修改资源始终需要一个资源上的(X)锁来维护资源的一致性。因此在死锁的情况下,如果可能,确定只读的资源访问,并使用脏读特性避免对应的锁请求。
 实现行版本控制
代替使用严格的锁架构来避免访问资源,可以通过已提交读快照或快照隔离级别来实施行版本控制。行版本控制隔离级别用于减少阻塞,但是由于是在tempdb中增加了一个可用的行版本,从而增加了tempdb的开销,尤其是tempdb空间不足的情况下。
ALTER DATABASE zhongyang
SET READ_COMMITTED_SNAPSHOT ON
 降低隔离级别
将包含SELECT语句的事务隔离级别降低为未提交读,这样SELECT语句就可以不请求(S)锁而读取数据,从而避免循环阻塞。但是如果需要依赖读取的数据进行进一步操作,那么这个方法就不可取。
 使用锁提示
 NOLOCK
 READUNCOMMITTED
避免给定会话请求(S)锁,作用于查询级别并且限于所应用到的表(及其索引),只允许用于SELECT语句中以及INSERT、DELETE、UPDATE语句的数据选择部分中。
最小化锁争用带来的脏读的副作用,只有在脏读可接受的情况下,才能使用这种技术。

要回复问题请先登录注册