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表的外键删除即可。