[seata]插入undo_log的前置镜像和后置镜像数据 和 查询出来的undo_log的数据不一致,而且是同一种序列化 FST

2024-07-15 349 views
1

dbfa9bfc93c1c9d36309468cf27e16b 这是插入的数据 52fa6acff1b8717f7c31076adbeaa14 这是查询的数据 d1ecd7a27d57fee805f2a5c1e2c21e1 这是拿undo_log回滚的数据, 他们的数据大小都不一致, seata-server:1.4.2 seata客户端

io.seata seata-spring-boot-starter 1.4.0

回答

7

现象是什么?无法回滚吗?

2

现象就是我采用了shardingjdbc+druid 插入数据 blob二进制数据,他会莫名奇妙的多出好多多余的数据出来,导致seata反序列化的时候一直失败,导致一直回滚失败

4

我发现问题了,shardingJdbc的代理,我们通过 setBlob()设置二进制的数据 ,他最终会在 ShardingPreparedStatement类,代理成setObjct()设置的内容,你们可以用最原生的JDBC,分别用setBlob() 和 setObjct()方法设置相同的内容,setObjct()方法会导致二进制的数据会不一样 b3ba7997fcb0b09897f36158f6fa704 c1a9fd4d34c67739798d3e8df31ba2d 0d72251f02cad4d017b0a3ae19fc5aa 2c4e5f5654d1297fbb151fd02468f48 根据以上提供的源码debug图

1

主要是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的技术

5

我们 已经 不setBlob了。。。