- 产生死锁的原因主要是:
(1)系统资源不足。
(2)进程运行推进的顺序不合适。
(3)资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
- 产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
- 交换事件死锁
主要是对任务流程的更新操作,同时又有删除操作,在执行更新未提交
例如:DZJG_CRM.dbo.S_CRM_BUSI_SalesServiceReport_TESK
- 交叉死锁
任务表查询 经办流程,同时有人提交,sql事物存在交叉处理导致程序死锁
"DZJG_CRM.dbo.sp_GetTaskMywork"
- 普通(页面)死锁
- 事物提交交叉死锁
sp_crm_LoanApplyCheckIn_2
f_GetNowProcNew
设计过程中的建议
下面有一些对死锁发生的一些建议:
1)对于频繁使用的表使用集簇化的索引;
2)设法避免一次性影响大量记录的T-SQL语句,特别是INSERT和UPDATE语句;
3)设法让UPDATE和DELETE语句使用索引;
4)使用嵌套事务时,避免提交和回退冲突;
5)对一些数据不需要及时读取更新值的表在写SQL的时候在表后台加上(nolock),如:Select * from tableA(nolock)
默认情况下,数据库没有锁定超时期限。也就是说一个会话在申请新的资源时,如果这个资源已经被其它进程锁定,那么本会话会一直处于等待状态。这样无疑是有问题的。我们可以通过SQL命令来设定锁请求超时。也可以访问全局变量 @@LOCK_TIMEOUT 来查看这个值。
当请求锁超过设定时间时,SQL Server将返回错误。我们的程序可以根据返回的错误来进行响应的处理,避免长时间的用户等待。
当然,使用这种方式来处理所有的锁请求是不合适的,也是不负责任的。在多数情况下是我们的程序的设计、实现的问题导致了死锁。在处理过程中,我们既要治标,更要治本。
备注:死锁无法彻底解决,只能根据死锁的条件去逐个调整,虽然不能完全避免死锁,但可以使死锁的数量减至最少。将死锁减至最少可以增加事务的吞吐量并减少系统开销