从SQL Server的Online Book里面描述Deadlock策略里面发现有下面的一种情况:
Worker threads. A queued task waiting for an available worker thread can cause deadlock. If the queued task owns resources that are blocking all worker threads, a deadlock will result. For example, session S1 starts a transaction and acquires a shared (S) lock on row r1 and then goes to sleep. Active sessions running on all available worker threads are trying to acquire exclusive (X) locks on row r1. Because session S1 cannot acquire a worker thread, it cannot commit the transaction and release the lock on row r1. This results in a deadlock.
- 工作线程。排队等待可用工作线程的任务可能导致死锁。如果排队等待的任务拥有阻塞所有工作线程的资源,则将导致死锁。例如,会话 S1 启动事务并获取行 r1 的共享锁(S 锁)后,进入睡眠状态。在所有可用工作线程上运行的活动会话正尝试获取行 r1 的排他锁(X 锁)。因为会话 S1 无法获取工作线程,所以无法提交事务并释放行 r1 的锁。这将导致死锁。
也就是说并不一定要是都是Update、Insert这种会上排它锁操作的语句才会造成死锁。只要在不同的线程里面访问了同一个资源(某个数据行)的情况下,一个Select动作碰上了一个Update动作也会产生死锁。你的SQL语句执行时间越长碰上这种情况的机会越大。看看下面这张图
-
左边的进程完全就是一个普通的查询语句,对资源上的也只是一个共享锁(S).而右边的进程是上了一个Index的排它锁(IX).跟通常意义上的两边都上排它锁才可能产生死锁的情况完全不一样,下面的图是我们写程序可以避免的死锁情况
-
怎么处理好SQL Server里面的死锁的话可以参照下面这篇文章:
里面提到了,要避免的Deadlock,把不同事务里面两个Update或者Insert资源的操作锁定资源顺序保持一致是最基本的,不过也就是能避免第二张图里面出现的情况。
-
-
而要避免第一张图的情况好像是不太可能,除非你每个SQL 语句都加上With Nolock,第一张图的情况基本上只能够通过减少查询时间,减少事务处理的时间来减少而无可避免。
-