不当事务代码引起的数据库死锁问题

24 篇文章 0 订阅

错误案例

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

UPDATE WP_IMAGE_SORT SET GMT_MODIFIED = SYSDATE,IMAGE_IDS = #imageIds# || IMAGE_IDS WHERE MEMBER_ID = #memberId# AND ALBUM_ID = #albumId#

以及

update WP_ALBUM set GMT_MODIFIED = sysdate, image_count = (select count(*) from wp_image where album_id= #id# and STATUS <![CDATA[<>]]> 'deleted') where id = #id# and member_id = #memberId#

错误分析

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

saveImg: { 
    ……
     //Transaction start
    imageBO.appendImageSort(memberId, album.getId(), imgId.longValue());
    ……
    winportAlbumDAO.updateAlbumImageCountAndLastModified(album.getId(), album.getMemberId());
    //Transaction end
   ……
} 
moveImg: { 
    ……
     //Transaction start
    winportAlbumDAO.updateAlbumImageCount(srcAlbumDO.getId(), memberId);
    ……
    imageBO.appendImageSort(memberId, targetAlbumDO.getId(), ids);
    //Transaction end
    ……
}

两个事务的处理代码顺序正好相反,相反的更新动作导致了死锁。
死锁的四要素:
互斥条件
请求与保持条件
不剥夺条件
循环等待条件
可以看出,前三条的都是事务引起的,因此大家以后要慎用事务处理或者设置事务级别,在确实需要使用 事务的时候,请打破循环条件(保持update语句调用顺序的一致性,而非首尾相连的颠倒次序)

注:
这里的问题简单了说,就是需要保持一致的更新顺序,比如
操作一:按顺序更新,A,B,C
操作二:按顺序更新,C,B,D
这样就有可能会导致,B,C和C,B这两个操作互相等待,导致死锁

处理方法很简单,把操作二变成B,C,D,因为两个操作都需要获得B,C这两把锁才能完成, 现在顺序调整成一致
就能保证如果拿到B这把锁,就能保证拿到C,完成事务,这样就不会导致两个操作互相等待了

支付宝曾经也出现过类似的问题的,在转帐的时候会涉及到两个帐号,也可能造成类似的互相等待的问题,
解决就是总是先锁帐号ID小的那个,即“保持update语句调用顺序的一致性”


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值