问题如下:
seata(1.30和1.42版本都有)安装配置工作正常后,经测试发现,mybatis-plus 的 BaseMapper 类里的 insert 方法,如果在插入数据时,不指定主键id,会导致插入的数据无法回滚。同时更新的数据是能正常回滚的。
具体测试类看下图的那行注释:
public void insertOrder(int userId, int goodsId, String goods, int count) { GoodsOrder goodsOrder = new GoodsOrder(); // goodsOrder.setId(101); // 必须指定主键id,否则插入的记录不能回滚 goodsOrder.setUserId(userId); goodsOrder.setGoodsId(goodsId); goodsOrder.setGoods(goods); goodsOrder.setCount(count); goodsOrderMapper.insert(goodsOrder); }
这是插入后不能回滚的数据证据:
触发回滚:There was an unexpected error (type=Internal Server Error, status=500). [500] during [GET] to [http://BATIS-SEATA-FEIGN-STOCK/stock/update_stock?goodsId=56&count=101] [StockFeignService#insertOrUpdateStock(int,int)]: [{"timestamp":"2022-04-19T12:54:21.572+0000","status":500,"error":"Internal Server Error","message":"库存下限错误","path":"/stock/update_stock"}]
数据没被回滚,还在:
107 398 56 北欧沙发 101
如下操作可以正常回滚:
- 如果给实体实例设定id=101(即把该行注释去掉)
- 或者如果使用 mapper.xml 里的原生SQL语句
问题描述完了,
期待你的回复!谢谢哈!
6条答案
按热度按时间9w11ddsr1#
请提供有效日志及信息证明无法回滚,是undolog没生成,还是生成了回滚有脏数据,你的证据就是你抛了个异常而已,无法证明跟seata有直接关系
xqnpmsa82#
seata_gc.log 只有这个log
数据表的seata_undo_log 是空的,在发生了回滚错误后。
这个我能证明是seata导致的:
因为我搭好分布式事务的环境,3个微服务,seata运行起,经测试,添加注解 @GlobalTransactional 是能发生3个微服务的回滚的。而去掉注解@GlobalTransactional后就不能回滚了。证明seata是起作用的。
然后问题在这套环境里,调试,对其中一个没回滚成功的微服务,如果代码写成 goodsOrder.setId(101); 在insert,即手动设置insert数据的主键,是能正常回滚的。如果不设置,则没有回滚插入的数据。
这个推理很明显。
环境是 MybatisPlus 3.1.0,Mysql 5.7,nacos,spring-cloud,openfeign
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-core</artifactId> <version>3.1.0</version> <scope>compile</scope> </dependency>
建议你们也搭建个环境试试,这个不完全是seata的问题,应该是结合了mybatis plus后产生的。我对我搭建的环境测试了一晚都是如此。
vuktfyat3#
我也遇到上面的问题,没有指定主键的id时根本不走MySQLUndoLogManager中的insertUndoLog方法
htrmnn0y4#
请提供一下驱动版本
5jvtdoz25#
我是在整合tkmybatis的时候不插入undo_log。。。
jmo0nnb36#
的确存在这个问题。
mybatis-plus 在处理自增不指定id插入时,默认使用0让数据库自己处理。
不清楚是否这个原因?
各位有简单一点的解决方案吗(不改表id自增的情况)?