最近生产环境出现一个问题,某张表里的primary key主键出现了重复冲突(duplicate key),应用层抛出了异常,但应用的其他不相关功能也受到了影响,比如查询数据失败。按道理,这属于不同事务之间的功能,应该不会受关联影响。
查看代码,spring.xml已经配置了事务管理器,对所有insert开头的插入方法增加了事务处理:
<tx:method name="insert*" propagation="REQUIRED">
这里的事务传播特性是REQUIRED:如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
虽然配置了事务,但在manager层,却对异常进行了捕获,这样在抛异常时,事务是不会回滚的。而MyCat有个坑的地方,当事务没有回滚时,失败的连接还在,导致其他事务的功能也会失败。
try {
mapper.insertData(model);
} catch (Exception e) {
LOGGER.error("insert data failed", e);
}
对于Spring已经声明了@Transactional,不能在方法里自己捕获unchecked exception,可以让Spring的AOP切入点自己去监听,从而将事务回滚掉。
所以方法里直接去掉try catch即可:
mapper.insertData(model);
目前MyCat的分布式事务为弱XA事务,这样是无法保证强一致性。当跨多个节点提交时,事务只能回滚那些提交失败节点上的操作,对于已经提交成功的节点,是无法进行回滚的。