一、死锁原理
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+1WaitFor Delay '00:01:00';
SELECT * FROM BROLLBACK 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+1WaitFor Delay '00:00:10';
SELECT * FROM B WITH(NOLOCK)ROLLBACK tran
结果:
c、在sql语句前加上SET LOCK_TIMEOUT,数据默认LOCK_TIMEOUT时间是10分钟
BEGIN tran
SET LOCK_TIMEOUT 3000UPDATE a SET dd=dd+1
--WaitFor Delay '00:00:10';
SELECT * FROM BROLLBACK tran
--3秒钟就会终止当前SQL的执行,不会影响后面的执行效率