我在MS SQL Server 2005之上运行的.NET 2.0 webapp上遇到非常罕见且烦人的SQL死锁.过去,我们一直在以经验的方式处理SQL死锁 - 基本上调整查询直到它工作.
然而,我发现这种方法非常不令人满意:耗时且不可靠.我更倾向于遵循确定性查询模式,这些模式将确保设计不会遇到任何SQL死锁.
例如,在C#多线程编程中,必须按照字典顺序执行一个简单的设计规则(如锁定),以确保不会发生死锁.
是否有任何SQL编码模式可以保证防死锁?
编写防死锁代码真的很难.即使以相同的顺序访问表,您仍可能遇到死锁[1].我在我的博客上写了一篇帖子,详细阐述了一些可以帮助你避免和解决死锁情况的方法.
如果要确保两个语句/事务永远不会死锁,则可以通过使用sp_lock系统存储过程观察每个语句使用哪些锁来实现它.要做到这一点,你必须非常快或使用带有holdlock提示的打开事务.
笔记:
任何一次需要多个锁的SELECT语句都会对智能设计的事务进行死锁,该事务以相反的顺序抓取锁.
在一般情况下,零死锁基本上是一个非常昂贵的问题,因为您必须知道每个正在运行的事务(包括SELECT)将要读取和修改的所有表/ obj.一般的哲学称为有序严格的两阶段锁定(不要与两阶段提交相混淆)(http://en.wikipedia.org/wiki/Two_phase_locking ;即使2PL也不保证没有死锁)
很少有DBMS实际实现严格的2PL,因为这样的事情导致了大量的性能(没有免费午餐),而所有的事务都在等待即使是简单的SELECT语句也要执行.
无论如何,如果这是你真正感兴趣的东西,请看一下SET ISOLATION LEVEL
SQL Server.您可以根据需要进行调整.http://en.wikipedia.org/wiki/Isolation_level
有关详细信息,请参阅关于可序列化的维基百科:http://en.wikipedia.org/wiki/Serializability
这就是说 - 一个很好的类比就像源代码修改:早期和经常检查.保持您的事务很小(在SQL语句的#,修改的行数#)和快速(挂钟时间有助于避免与其他人发生冲突).在一次交易中做很多事情可能是好的和整洁的 - 总的来说我同意这个理念 - 但是如果你遇到很多僵局,你可能会将转换分解为较小的转换,然后在移动时检查它们在应用程序中的状态.TRAN 1 - OK Y/N?如果是Y,发送TRAN 2 - OK Y/N?等等
顺便说一句,在我多年担任DBA和开发人员(多用户数据库应用程序测量成千上万的并发用户)的过程中,我从来没有发现死锁是一个如此大的问题,我需要特别认识它(或改变隔离不知所措等等.