这是插入的数据 这是查询的数据 这是拿undo_log回滚的数据, 他们的数据大小都不一致, seata-server:1.4.2 seata客户端
[seata]插入undo_log的前置镜像和后置镜像数据 和 查询出来的undo_log的数据不一致,而且是同一种序列化 FST
回答
现象是什么?无法回滚吗?
现象就是我采用了shardingjdbc+druid 插入数据 blob二进制数据,他会莫名奇妙的多出好多多余的数据出来,导致seata反序列化的时候一直失败,导致一直回滚失败
我发现问题了,shardingJdbc的代理,我们通过 setBlob()设置二进制的数据 ,他最终会在 ShardingPreparedStatement类,代理成setObjct()设置的内容,你们可以用最原生的JDBC,分别用setBlob() 和 setObjct()方法设置相同的内容,setObjct()方法会导致二进制的数据会不一样 根据以上提供的源码debug图
修复:https://github.com/seata/seata/pull/3555 分析:https://github.com/seata/seata/issues/3541
检查一下你的驱动版本和client版本,如果符合上面的条件的话,任意升级其中一个可以解决
主要是ShardingJdbc他会代理我们的setBlob(),他都会代理成SetObject(),在jdbc8.0.22版本的前面,排除jdbc5.的版本,他的逻辑是 Map<Class,xxx> map, map.get(Blob.class),但是我们seata之前是SerialBlob的class,他用Map.get(SerialBlob.class),他拿到是一个空,然后他就会将SerialBlob用Java序列化进行传输.下面2个图是 mysql8.0.22的setObject()和mysql8.0.28的setObject()逻辑。
ShardingJdbc和seata整合,确实很多问题,ShardingJdbc它不支持SavePoint技术,但是我们Seata用 select for update+ @GloableLock , SelectForUpdate执行器的逻辑是申请全局锁的逻辑当中采用了SavePoint的技术
我们 已经 不setBlob了。。。