记一次线上数据库死锁定位

在开发过程中,操作数据库总会涉及到批量操作。有些批量操作可以利用multiquery更新数据库,但有些不可,例如对于同一张表不同字段的多行更新。我们经常会把这种操作放到一个事务里面,由于都是按照主键更新,所以性能上不会有大问题,例如这样:

@Transactional
    public void update(List<DAO> daoList)
    {
        for (DAO dao : daoList) {
            daoMapper.updateByPrimaryKeySelective(dao);
        }

    }

但是如果不注意的话,会出现数据库死锁,利用MySql自带的innodb引擎监控日志(show engine innodb status),看到最近的死锁:

2017-09-28 00:19:24 0x7f70134b1700
*** (1) TRANSACTION:
TRANSACTION 205776344, ACTIVE 71 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1136, 7 row lock(s), undo log entries 85
MySQL thread id 2552, OS thread handle 140118527325952, query id 17080031 xxx.xx.xx.xxx sql
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 15 page no 135560 n bits 200 index PRIMARY of table `db`.`table` trx id 205776344 lock_mode X locks rec but not gap waiting
Record lock, heap no 67 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030313032315354463132333833373937; asc 170928001021STF12383797;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;
 2: len 7; hex 30000008370881; asc 0   7  ;;


*** (2) TRANSACTION:
TRANSACTION 205775866, ACTIVE 129 sec starting index read
mysql tables in use 1, locked 1
7 lock struct(s), heap size 1136, 93 row lock(s), undo log entries 149
MySQL thread id 2544, OS thread handle 140119336752896, query id 17080690 xxx.xx.xx.xxx sql
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 15 page no 135560 n bits 200 index PRIMARY of table `afbet`.`t_facts_market_stateful_messages` trx id 205775866 lock_mode X locks rec but not gap
Record lock, heap no 5 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030303930395354463132333833303738; asc 170928000909STF12383078;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;


Record lock, heap no 9 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030303931305354463132333833303837; asc 170928000910STF12383087;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;


Record lock, heap no 12 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030303931345354463132333833313037; asc 170928000914STF12383107;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;
 2: len 7; hex 30000008371103; asc 0   7  ;;


Record lock, heap no 14 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030303931345354463132333833313336; asc 170928000914STF12383136;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;
 2: len 7; hex 30000008370ad3; asc 0   7  ;;


Record lock, heap no 15 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030303931365354463132333833313332; asc 170928000916STF12383132;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;
 2: len 7; hex 3000000837103d; asc 0   7 =;;


Record lock, heap no 16 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030303931385354463132333833313934; asc 170928000918STF12383194;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;
 2: len 7; hex 300000083708e4; asc 0   7  ;;

Record lock, heap no 17 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030303932305354463132333833323135; asc 170928000920STF12383215;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;
 2: len 7; hex 300000083714e1; asc 0   7  ;;


Record lock, heap no 18 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030303932305354463132333833323137; asc 170928000920STF12383217;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;
 2: len 7; hex 3000000837141b; asc 0   7  ;;


Record lock, heap no 19 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030303932305354463132333833323138; asc 170928000920STF12383218;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;
 2: len 7; hex 30000008370deb; asc 0   7  ;;


Record lock, heap no 21 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030303932345354463132333833323733; asc 170928000924STF12383273;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;
 2: len 7; hex 30000008370a0d; asc 0   7  ;;




Record lock, heap no 67 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030313032315354463132333833373937; asc 170928001021STF12383797;;
 1: len 6; hex 00000c43e3fa; asc    C  ;;
 2: len 7; hex 30000008370881; asc 0   7  ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 15 page no 135559 n bits 112 index PRIMARY of table `db`.`table` trx id 205775866 lock_mode X locks rec but not gap waiting
Record lock, heap no 39 PHYSICAL RECORD: n_fields 12; compact format; info bits 0
 0: len 23; hex 3137303932383030303834395354463132333833303332; asc 170928000849STF12383032;;
 1: len 6; hex 00000c43e5d8; asc    C  ;;
 2: len 7; hex 2a0000080726b6; asc *    & ;;


*** WE ROLL BACK TRANSACTION (1)

发现有两个Transaction发生死锁

原因:

批量更新,并且每个dao可以多线程更新(在不同事务内同时请求更新),而且没有按照一定顺序。例如事务1更新id为1,2,3的数据,事务2更新id为3,2,1的数据,这样就会发生死锁

修改方案:

按顺序更新,例如把入参改为TreeSet,并且dao对象实现Comparable接口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Oracle数据库死锁是指两个或多个事务相互等待对方释放所持有的资源,导致事务无法继续执行,并且无法通过自动机制解决该冲突。当发生死锁时,数据库会检测到该情况,并选择一个事务进行回滚,以解除死锁。 出现死锁的原因通常是事务并发执行时对资源的竞争导致的,例如不同的事务同时请求相同的资源但按不同的顺序获取,或者事务持有了某些资源并请求其他事务所持有的资源。 为了处理Oracle数据库中的死锁问题,可以采取以下几种方法: 1. 检测死锁:Oracle数据库提供了系统视图和命令来检测死锁,例如使用`DBA_DDL_LOCKS`视图或`SELECT * FROM V$LOCKED_OBJECT`命令来查看被锁定的对象。 2. 解决死锁:一旦检测到死锁,Oracle数据库会自动选择一个事务进行回滚以解除死锁。这个过程是自动的,可以通过配置数据库参数来调整死锁检测和解除的行为。 3. 优化事务设计:设计良好的事务可以减少死锁的发生。例如,可以按照固定的顺序获取资源,或者减少事务之间对同一资源的竞争。 4. 调整数据库参数:可以通过调整Oracle数据库的参数来减少死锁的风险。例如,通过调整`DML_LOCKS`参数来控制事务对数据行的锁定方式。 5. 使用锁超时机制:可以在事务等待资源时设置锁超时,如果超过一定时间仍未获取到资源,则自动回滚事务。这可以减少死锁持续时间,但也可能导致事务执行失败。 以上是一些处理Oracle数据库死锁问题的常见方法,具体应根据实际情况选择合适的解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值