Seata事务回滚数据将字段值回滚为1

现象

数据字段status
mysql类型tinyint
存储value=2

  1. 更新语句更新表中的其他字段并且覆盖写入status=2(该字段本身value=2)
  2. 运行到其他服务的业务出现错误,全局事务回滚
  3. 其他字段回滚正常,status数据回滚成value=1

排查

测试接口断点卡主, 查看seata的undolog表的数据

        // 示例数据(Base64 编码的 Java 序列化数据) 手动去掉0x前缀
        String base64Data = "7B22406";
        byte[] bytes = DatatypeConverter.parseHexBinary(base64Data);

        // 反序列化
        String jsonString = new String(bytes, StandardCharsets.UTF_8);
        System.out.println(object);
{
    "@class": "io.seata.rm.datasource.undo.BranchUndoLog",
    "branchId": 2090276239587073061,
    "sqlUndoLogs": [
        "java.util.ArrayList",
        [
            {
                "@class": "io.seata.rm.datasource.undo.SQLUndoLog",
                "sqlType": "UPDATE",
                "tableName": "xxxxx",
                "beforeImage": {
                    "@class": "io.seata.rm.datasource.sql.struct.TableRecords",
                    "tableName": "xxxx",
                    "rows": [
                        "java.util.ArrayList",
                        [
                            {
                                "@class": "io.seata.rm.datasource.sql.struct.Row",
                                "fields": [
                                    "java.util.ArrayList",
                                    [
                                        

                                        {
                                            "@class": "io.seata.rm.datasource.sql.struct.Field",
                                            "name": "status",
                                            "keyType": "NULL",
                                            "type": -7,
                                            "value": true
                                        },
                                        {
                                            "@class": "io.seata.rm.datasource.sql.struct.Field",
                                            "name": "update_time",
                                            "keyType": "NULL",
                                            "type": 93,
                                            "value": [
                                                "java.time.LocalDateTime",
                                                1739256077000
                                            ]
                                        }
                                    ]
                                ]
                            }
                        ]
                    ]
                },
                "afterImage": {
                    "@class": "io.seata.rm.datasource.sql.struct.TableRecords",
                    "tableName": "account_member_bank_info",
                    "rows": [
                        "java.util.ArrayList",
                        [
                            {
                                "@class": "io.seata.rm.datasource.sql.struct.Row",
                                "fields": [
                                    "java.util.ArrayList",
                                    [
                                        {
                                            "@class": "io.seata.rm.datasource.sql.struct.Field",
                                            "name": "status",
                                            "keyType": "NULL",
                                            "type": -7,
                                            "value": true
                                        },
                                        {
                                            "@class": "io.seata.rm.datasource.sql.struct.Field",
                                            "name": "update_time",
                                            "keyType": "NULL",
                                            "type": 93,
                                            "value": [
                                                "java.time.LocalDateTime",
                                                1739256179000
                                            ]
                                        }
                                    ]
                                ]
                            }
                        ]
                    ]
                }
            }
        ]
    ]
}

理解

Seata在生成undolog的rollback_info时,转换status的时候把tinyint类型的数据("type": -7) 当做Boolean进行处理了,作为true在保存到rollback_info,当回滚时【value=true】反序列化到【value=1】写入

解决办法

  1. 状态字段不使用tinyint 使用int或者varchar等其他字段
  2. 在更新字段时,将status字段置为null,不更新该字段,则不会回滚该字段
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容