一例线上数据库死锁的排查,以及引起的思考

某日,DBA反映线上数据库报警,检测到死锁,跟踪到发生死锁等待的两条SQL语句分别为:

Java代码   收藏代码
  1. UPDATE WP_IMAGE_SORT SET GMT_MODIFIED = SYSDATE,IMAGE_IDS = #imageIds# || IMAGE_IDS WHERE MEMBER_ID = #memberId# AND ALBUM_ID = #albumId#  


以及

Java代码   收藏代码
  1. update WP_ALBUM set GMT_MODIFIED = sysdate,   
  2. image_count = (select count(*) from wp_image where album_id= #id# and STATUS <![CDATA[<>]]> 'deleted')    
  3. where id = #id#   
  4. and member_id = #memberId#  


回忆大学里的课程,死锁一般是由于资源互相占用并且无法释放导致的,因此重点排查IBANK中相关数据表的操作,发现在saveImg和moveImg两个方法中存在以下逻辑

Java代码   收藏代码
  1. saveImg  
  2. {  
  3.      ……  
  4. //Transaction start  
  5.      appendImageSort(memberId, album.getId(), imgId.longValue());  
  6.      ……  
  7. winportAlbumDAO.updateAlbumImageCountAndLastModified(album.getId(), album.getMemberId());  
  8. //Transaction end  
  9. ……  
  10. }  

        
Java代码   收藏代码
  1. moveImg  
  2. {  
  3.      ……  
  4.      //Transaction start  
  5. winportAlbumDAO.updateAlbumImageCount(srcAlbumDO.getId(), memberId);  
  6. ……  
  7. imageBO.appendImageSort(memberId, targetAlbumDO.getId(), ids);  
  8. //Transaction end  
  9.      ……  
  10. }  


众所周知,死锁的四要素
1、互斥条件
2、请求与保持条件
3、不剥夺条件
4、循环等待条件

可以看出,前三条的都是事务引起的,因此大家以后要慎用事务处理或者设置事务级别,在确实需要使用事务的时候,请打破循环条件(保持update语句调用顺序的一致性,而非首尾相连的颠倒次序)

和同事聊起事务这类死锁问题的时候,发觉电子支付时这类情况比较常见,比如账户A转账100元到账户B,涉及到事务性的操作(A-100,B+100),如果牵涉到反复倒帐的情况,就有可能发生死锁,据说当初解决的方法,就是在事务当中,统一按照id大小进行处理,即都是先小ID处理,在大ID处理,简单优雅地解决了此类问题
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值