Back

SQL SERVER DEADLOCK

SQL SERVER DEADLOCK



6.13.6 死锁及其解除

封锁机制的引入能解决并发用户访问数据的一致性问题,但由此会引起进程间的死锁问题。引起死锁的主要原因是两个进程已各自锁住一个页,但又要求访问被对方锁住的页。

更常见的情况是,一个事务独占了其他事务正在申请的资源,且若干个这样的事务形成一个等待圈。例如:用户A和B按照表6 - 1 3的时间顺序执行了一些操作,则在T 3时间点会产生死锁。

表6-13 用户操作过程

用户T 1 T 2 T 3

A 查询TA B 1信息(h o l d l o c k) 修改TA B 2数据

B 查询TA B 2信息(h o l d l o c k) 修改TA B 1数据

SQL Server能自动发现并解除死锁。当发现死锁时,它会选择其进程累计的C P U时间最少者所对应的用户作为“牺牲者”(令其夭折),以让其他进程能继续执行。此时SQL Server发送错误号1 2 0 5(@ @ e r r o r = 1 2 0 5)给牺牲者。

为了尽可能避免死锁的出现,建议你:

• 在所有的事务中都按同一顺序来访问各个表。尽可能利用存储过程来完成一个事务,以能保证对各表的访问次序都是一致的。

• 除非有“可重复读”的必要性,否则不要使用h o l d l o c k选项。

• 事务应该尽量小且应尽快提交。

• 避免人工输入操作出现在事务中或是同时对该表施加h o l d l o c k。

• 避免并发地执行许多像I N S E RT、U P D AT E、D E L E T E这类数据修改语句。

如下的两个事务,是按不同的顺序来访问表A及表B,它很容易引起死锁。

BEGIN TRAN X BEGIN TRAN X

U P D ATE A UPDATE B

U P D ATE B UPDATE A

COMMIT TRAN COMMIT TRAN

封锁机制有以下特征:

1) 封锁粒度(及隔离级别)与并发度是一对矛盾。数据加锁的个数直接影响可并行访问数据的用户数。当一个应用系统要求有较高的并发度而且可接受近似值的查询结果时(如统计信息),建议使用隔离级别0。

2) SQL Server支持A N S I标准隔离级别0、1、2及3。缺省的事务隔离级别为1。锁的类型有:共享(S)锁、排它(X)锁及更新(U)锁。

3) SQL Server能自动发现并解除死锁。用户应遵照一些必要的开发原则,尽量避免出现死锁。