当前位置:数据库 > SQLServer >>

关于SQL Server中的死锁详解介绍(1/3)

 一些基础知识
    要理解SQL Server中的死锁,更好的方式是通过类比从更大的面理解死锁。比如说一个经典的例子就是汽车(主体)对于道路(资源)的征用,如图1所示。

对于死锁的直观理解

     在图1的例子中,每队汽车都占有一条道路,但都需要另外一队汽车所占有的另一条道路,因此互相阻塞,谁都无法前行,因此造成了死锁。由这个简单的例子可以看出,发生死锁需要四个必要条件,如下:

1)互斥条件:

    主体对于资源是独占的,图1中每条汽车道只能跑一队汽车,不能跑第二队。

 2)请求和等待条件:

     指主体已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它主体占有,此时请求主体阻塞,但又对自己已获得的其它资源保持不放。在图1中,每队汽车已经占有了一条车道,又想获得另一条由其它车队占有的车道,造成阻塞。

 3)不剥夺条件

    指的是主体已经获得的资源在完成其目标之前不能被释放。在图1中,目标指的是汽车可以通过车道,不剥夺指的是在完成这个目标之前,车队并不会让出其已占的车道。

 4)环路等待条件

    指在发生死锁时,必然存在一个主体——资源的环形链,即主体集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。在图1中可以看出,四条车道和四队汽车正好符号环路等待的条件,车队1希望获得车队2占有的车道,车队2希望获得车队3占有的车道,车队3希望获得车队4占有的车道,车队4反过来又希望获得车队1占有的车道,形成一个环路。

 死锁在进程中的定义
    下面让我们再缩小死锁的范围,回到计算机的世界。在计算机中,主体的这个抽象的词被更具体的进程所替代,而资源缩小到计算机所使用的资源。在计算机中,死锁是由阻塞所引起。因此在开始之间,我想简单介绍一下进程的几种状态,如果有兴趣,也可以参看我之前的一篇文章:http://www.cnblogs.com/CareySon/archive/2012/05/04/ProcessAndThread.html.

    简单来说,进程是组织资源的最小单位,多道操作系统中允许并发进行,每一道进程都像图1所示的汽车那样,需要前进,在前进的过程中,需要各种资源以及CPU,图2是不考虑进行创建销毁等状态,简单概述进程的几种状态。

   

.进程的几种状态

 

    很多资源是可以共享的,比如内存。但对于打印机等资源来说就需要独占。图2中的几种状态简单理解是,当进程没有所需的资源时,比如说等待IO,等待打印机,这时是阻塞状态。而当进程获得了这些资源时,就可以变为就绪状态,在就绪状态的进程再获得CPU时,就变为执行状态。而执行的过程中,CPU被剥夺了就继续变为就绪状态,或是当需要其它资源时,就会继续变为阻塞状态。以此往复。

    在操作系统中,有些资源可以是不可剥夺资源,比如打印机,当打印机被一个进程占用时,另一个进程就会被阻塞。还有一类资源是要重点强调的,这类资源是临时性资源,比如进程产生的信号量,消息,缓冲区内的消息,多个进程或线程访问这类资源时更容易引起死锁。在SQL Server中产生的死锁其实就是由这类资源所造成的。

    当两个或多个进程既然有了当前的资源,又需要额外的资源时,满足了上面所述死锁的四个条件时,就会产生死锁。

 死锁在SQL Server中的定义
     在SQL Server中,阻塞更多的是产生于实现并发之间的隔离性。为了使得并发连接所做的操作之间的影响到达某一期望值而对资源人为的进行加锁(锁本质其实可以看作是一个标志位)。当一个连接对特定的资源进行操作时,另一个连接同时对同样的资源进行操作就会被阻塞(当然了,这和锁之间的兼容性有关,关于锁更深入的讨论超出了本文的范围,关于这部分内容可以看我的另一篇文章:T-SQL查询进阶—理解SQL Server中的锁),阻塞是死锁产生的必要条件。

    下面,我们通过一个简单的例子来看死锁。

     首先,要出现死锁,一定要满足前面提到死锁出现的四个必要条件,图3中可以清楚的看到这两个连接(SPID52和SPID55)是如何满足这四个条件的。

  

Lock Monitor
    图3中死锁后可以看到,SQL Server并不会让死锁僵持下去,而是通过一个叫Lock Monitor的线程定期进行检测(默认是5秒)。当发现死锁后,会剥夺其中一个SPID占有的资源,好让另一个SPID执行下去,具体剥夺哪一个SPID基于如下两个因素:

 1.死锁的优先级。

    2.在死锁优先级相同的情况下,根据开销,开销小的事务将会被剥夺

 

    下面,还是根据图3中的例子,我们设置死锁优先级,使得左边的事务被剥夺回滚,如图4所示。

   

.设置死锁优先级后,优先级低的SPID被剥夺

 

SQL Server中死锁的检测
    首先要理解,在多并发的环境中,死锁是不可避免的,只能尽量的通过合理的数据库设计,良好的索引,适当的查询语句以及隔离等级来尽量的减少。因此,检测死锁的目的是知道哪里可能会产生死锁,通过对检测到的死锁进行分析后,尽量的优化查询/索引/隔离等级来降低死锁发生的可能性。

    查看死锁有两种方式,一种是通过服务端的Trace来做,另一种是通过SQL Profiler,首先让我们来看通过Trace来抓死锁。

 

1 2 3
补充:数据库,Mssql
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,