死锁的形成以及处理

一、死锁原理

      a、根据操作系统中的定义:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。

二、死锁的四个必要条件:
     a、互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
     b、请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
     c、非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
     d、循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。

三、避免死锁

     a、按同一顺序访问对象。

     b、避免事务中的用户交互。

     c、保持事务简短并处于一个批处理中。

     d、使用较低的隔离级别。

四、查看死锁例句

     开两个查询窗口,分别执行下面两段sql

     BEGIN tran
          UPDATE a SET dd=dd+1

          WaitFor Delay '00:01:00';
          SELECT * FROM B

      ROLLBACK tran

     

     BEGIN tran 
        UPDATE B SET age=age+1 
        WaitFor Delay '00:01:00';
        SELECT * FROM A     
    ROLLBACK tran

  

   五、针对上面语句出现死锁情况的解决方法

         a、根据上面提到的按同一顺序访问对象(调换一下update跟select 执行顺序)

        BEGIN tran 
            SELECT * FROM A    --将select语句放在前,update语句放在后
            WaitFor Delay '00:00:30';
            UPDATE B SET age=age+1     
       ROLLBACK tran

      

        b、在SELECT语句加With(NoLock),加With(NoLock)可能会导致脏读。

         BEGIN tran 
             UPDATE B SET age=age+1
             WaitFor Delay '00:00:10';
             SELECT * FROM A WITH(NOLOCK)    --select语句上加上with(NOLOCK),有效的避免了死锁
         ROLLBACK tran

         

         还是示例一中的语句,只是加上了WITH(NOLOCK)   

          BEGIN tran
                UPDATE a SET dd=dd+1

                WaitFor Delay '00:00:10';
                SELECT * FROM B WITH(NOLOCK)

          ROLLBACK tran

          结果:

         

         c、在sql语句前加上SET LOCK_TIMEOUT,数据默认LOCK_TIMEOUT时间是10分钟

    BEGIN tran
      SET LOCK_TIMEOUT 3000

      UPDATE a SET dd=dd+1

      --WaitFor Delay '00:00:10';
      SELECT * FROM B

    ROLLBACK tran

          --3秒钟就会终止当前SQL的执行,不会影响后面的执行效率

         

        

    

原文地址:https://www.cnblogs.com/starts/p/5307767.html