外键导致的事务问题的解决方案

Exception分析

异常内容:

com.zaxxer.hikari.pool.ProxyConnection   : HikariPool-1 - Connection com.mysql.cj.jdbc.ConnectionImpl@192ef0c0 marked as broken because of SQLSTATE(08S01), ErrorCode(0)
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

The last packet successfully received from the server was 60,030 milliseconds ago. The last packet sent successfully to the server was 60,030 milliseconds ago.
    at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-java-8.0.29.jar:8.0.29]
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) 

A微服务的方法伪代码如下:

    @Override
    @Transactional
    public Result handleA(String plantId) {
        Result<String> resultVO = new Result<>();
        //删除A表的数据。
        if (locationInt > 0) {
            //delete tableA where id = ?
            baseMapper.delete(plantId);
        }
        
        try {
            resultVO = feign.updateTableB(plantId);
        } catch (Exception e) {
            // 异常处理,可以抛出回滚或日志记录然后邮件通知运维处理
        } finally {
        }
        resultVO.setResult(ResultConstant.RETURN_SUCCESS);
        resultVO.setMsg("操作成功");
        return resultVO;
    }

B微服务的伪代码如下:

    @Override
    @Transactional
    public Result updateTableB(String plantId) {
        Result<String> resultVO = new Result<>();
        resultVO = baseMapper.updateTableB(plantId);
        resultVO.setResult(ResultConstant.RETURN_SUCCESS);
        resultVO.setMsg("操作成功");
        return resultVO;
    }

在A微服务执行了delete table2语句。然后通过feign远程调用B微服务,B微服务里面执行update table1语句update table1 set 字段1 = ? where ID = ?。微服务B的update语句报com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure异常。

刚开始时不清楚为什么在A微服务调用B微服务的时候,B微服务总是报这个异常。然后把A微服务的@Transactional事务删除,就发现B微服务正常了,没有出现异常。然后仔细分析mysql的事务

查看当前事务:

select * from information_schema.innodb_trx;

 查看事务等待:

select * from information_schema.INNODB_LOCK_WAITS;

 在这里408944835事务id是A方法的事务,408946024是B方法的事务,从事务来看,B方法一直在等待A方法的事务锁释放。由于A方法远程调用B方法,B方法还在等待A方法的锁释放,B方法无法获取锁,导致B方法的update语句无法执行,最终到B方法抛出CommunicationsException异常。

然后反复查看A方法和B方法,发现者两个方法并有没同时操作B表。在A方法里面只操作了A表,B方法里面只操作了B表,应该是不会导致B方法的事务等待A方法的事务释放。后来突然想到为了画ER图,在A方法加了外键指向B方法。这样就导致了A方法事务未释放,B方法事务无法获取锁,导致B方法等待连接超时,最终报CommunicationsException异常。

解决方案:把A表指向B表的外键删除即可。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值