一个典型的数据库操作事务死锁分析-阿里云开发者社区

开发者社区> 长征2号> 正文

一个典型的数据库操作事务死锁分析

简介:
+关注继续查看

【表A】与【表B】之间有外键约束(具体怎么约束的无所谓,因为外键和事务死锁没有绝对关系)。【表A】=主键表,【表B】=外键表。
公司有几位程序员写的代码总是出现死锁,现在将事务死锁情况重现.

using(事务)
{
    
try{
        
for()//一个循环
        {
            
if(查询【表A】有该【记录】==false)//这个查询没有用当前事务的数据库连接,而是新开一个数据库连接查询数据库
            {
                将【记录】插入【表A】;
                插入【表B】;
            }
        }
        事务.提交();
    }
catch{
        事务.回滚();
    }
}

 

4月25日早9:00补充:以上代码逻辑如果放在一个存储过程里面,是没有问题的。但是放在C#中,程序员稍不注意,就很可能出现问题。出现问题的关键地方在“查询【表A】”。C#中,如果查询【表A】和当前的事务不是同一个数据库连接,而是新开一个连接,就会死锁(可以看留言中我的回复)。所以:要么
1,查询【表A】改为使用当前事务的数据库连接(推荐用这种方法)
2,要么按下面的进行代码改造,将事务移到循环体内。
当循环只有1次的时候,上面代码运行没有问题。
一旦循环大于1次的时候,死锁立即出现,运行SQL Server 2005的sp_who_lock,发现死锁的地方正是“查询【表A】”这块。为什么呢?
因为:第1次循环,插入【表A】后,事务将【表A】设置了独占锁,但是第1次循环完后,事务并没有提交,也就没有解开【表A】上的独占锁。因为表A被独占锁了,所以第2次循环时,“查询【表A】”这个操作进行不下去(后面的插入【表A】更是如此),一直在等待事务提交以解开锁,但是事务运行到第2次循环的查询【表A】就死了,循环无法继续进行,也就不能运行到循环外边的事务.提交(),【表A】的独占锁永远没法解开死锁就这样产生了。

既然知道了死锁的原因是因为循环里面没有解开独占锁,所以我们应该把事务.提交()放置在循环内。另外根据事务体的逻辑尽量少的原则,我们把事务的声明移植循环体内,使事务体的代码行数尽量少。代码如下。

 

for()//一个循环
{
    
bool 有记录=查询【表A】有该【记录】;//将这个查询移出事务是良好的编码习惯,虽然这里不必要
    using(事务)
    {        
        
try{
            
if(有记录==false)
            {
                将【记录】插入【表A】;
                插入【表B】;
            }
            事务.提交();
        }
catch{
            事务.回滚();
        }
    }
}

经过以上改造之后,几位程序员写的业务运行正常。

由此总结:
1,在C#等程序代码中使用事务,并在事务内进行查询的时候,特别要小心,确保该查询和事务使用的是同一个数据库连接。防止表被独占死锁。
2,事务体内应尽可能少的逻辑,尽可能少的代码行数。
3,4月25日9:00补充:防止事务死锁最好的方法,还是大家推荐的用存储过程,在存储过程里面使用事务(只不过门槛稍高,手工活儿稍多)


本文转自Kai的世界,道法自然博客园博客,原文链接:http://www.cnblogs.com/kaima/archive/2008/04/24/1167550.html,如需转载请自行联系原作者。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
云数据库的性能优化措施|学习笔记
快速学习云数据库的性能优化措施
3 0
云数据库的读写分离操作|学习笔记
快速学习云数据库的读写分离操作
4 0
构建多架构镜像的最佳实践
如今,Docker 容器镜像可以支持多种架构/平台,多架构镜像的构建已经成为了必备技能。
20 0
云数据库的数据迁移|学习笔记
快速学习云数据库的数据迁移
4 0
2020年全球程序员收入报告出炉,字节跳动成唯一上榜中国公司
Levels.fyi 网站于日前发布了一份 2020 年度程序员收入报告。报告中的薪酬数据反映的是在过去一年中收集的年度薪酬总额中位数,包括工资、股票和奖金。
1 0
云数据库安全设置|学习笔记
快速学习云数据库安全设置
5 0
【第17个代码模型】使用 PreparedStatement 操作数据库(PrepareStatement 查询案例)|学习笔记
快速学习 【第17个代码模型】使用 PreparedStatement 操作数据库(PrepareStatement 查询案例)
5 0
云数据库 MySQL 版的优势和使用场景|学习笔记
快速学习云数据库 MySQL 版的优势和使用场景
6 0
阿里云使用体验感
实用 阿里云 快捷 信息化
4 0
HTML5 Web 存储|学习笔记
快速学习 HTML5 Web 存储
1 0
+关注
1703
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载