mysql 第一个事务 创建数据,第二个事务修改同一条数据 Lock wait timeout exceeded 怎么解决?

查看 59|回复 3
作者:linuxsteam   
伪代码:
Class A {
        @Transactional(rollbackFor = Exception.class)
        public String transactionA() {
            Object savepoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
            try {
                // 省略可能报错的代码
                TableA a = new TableA();
                a.setId(1);
                tableAMapper.insert(a);
            }catch(Exception e) {
                e.printStackTrace();
                TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savepoint);
            }finally {
                LogMapper.insert(new Log("time","method","request","response"));
            }
        }
    }
    Class B {
        @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
        public void transactionB() {
            Object savepoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
            try {
                // 省略可能报错的代码
                TableA a = new TableA();
                a.setId(1);
                a.status(2);
                tableAMapper.update(a);
            }catch(Exception e) {
                e.printStackTrace();
                TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savepoint);
            }finally {
                LogMapper.insert(new Log("time","method","request","response"));
            }
        }
    }
TableA 表的 id 有主键约束,唯一索引。其他没有任何索引。
上面代码会产生 Lock wait timeout exceeded 的错误。
我通过检索资料,大概了解到问题原因,是事务 A 中tableAMapper.insert(a);触发了(行、排他锁),事务 B 里一直拿不到锁,导致超时。
但是我还想事务 B 拥有自己的事务,并且进行手动回滚。(因为我想在哪怕报错的时候 也要进行一段日志记录的数据库插入操作)
不知道有没有解决办法。或者其他思路?

tablea, atus, sert, rans

cnhongwei   
那你不要在 B 中开新事务,而是记录 Log 的类中开新事务。
missya   
A 和 B 方法是怎么调用的,A 中调用 B ?还是同时分别调用?
SvenWong   
看错误就是锁等待超时了,但是具体解决还是要看场景,比如你的 B 事务中对 TableA 的更新是否在单独线程,以及先后顺序,A 事务 insert TableA 之后,是否还有大量的代码操作,导致 A 事务迟迟无法提交等等
您需要登录后才可以回帖 登录 | 立即注册

返回顶部