一、功能简介genRollSQL是 gt-checksum v4.0.0 新增的核心参数配合maxRollRowNum和rollFileDir一起使用用于在生成修复 SQL 的同时自动生成反向回滚 SQL。参数说明参数默认值可选值说明genRollSQLOFFON/OFF/ 自定义表名控制是否生成回滚 SQLmaxRollRowNum10000正整数单表待修复行数超过该阈值时不生成回滚 SQLrollFileDirrollsql目录路径回滚 SQL 文件存储目录三种genRollSQL模式的区别模式行为OFF不生成回滚 SQL默认行为ON对所有校验的表生成回滚 SQL自定义表名仅对指定的表生成回滚 SQL支持逗号分隔多个表名支持%通配符使用方式非常简单在配置文件gc.conf中添加几行genRollSQLONrollFileDirrollsqlmaxRollRowNum10000二、功能作用及使用场景深入解读2.1 为什么需要回滚 SQL在生产环境中执行数据修复面临的风险远比测试环境复杂场景一审计与合规在金融、医疗等对数据变更审计要求严格的行业不仅需要知道改了什么还需要知道怎么改回去。回滚 SQL 是修复操作可审计性的重要组成部分。场景二修复逻辑误判在复杂的类型映射、字符集转换场景下校验工具判定的差异可能只是格式差异而非真实数据差异例如DECIMAL精度差异、utf8mb4_general_civsutf8mb4_0900_ai_ci的 collation 差异。修复后业务验证不通过需要回退。场景三修复导致业务中断修复 SQL 中的DELETE或UPDATE可能与正在运行的业务事务产生锁冲突或者修复了业务正在使用的数据行导致业务报错。此时需要快速回退恢复原状。2.2 回滚逻辑是如何工作的gt-checksum 的回滚 SQL 生成采用反向映射策略对每条修复 SQL生成一条语义相反的回滚 SQL。核心映射关系修复 SQL 类型回滚 SQL 类型说明DELETE FROM ... WHERE ...INSERT INTO ... VALUES(...)目标端删除的行回滚时重新插入INSERT INTO ... VALUES(...)DELETE FROM ... WHERE ...目标端插入的行回滚时删除TRUNCATE TABLE ...特殊处理仅在目标端整表为空时生成详见 2.3DELETE → INSERT 的转换过程修复 SQL 中的DELETE语句包含WHERE条件其中的列-值对就是被删除行的数据。回滚生成器解析WHERE子句提取所有列名和对应的值重新组装为INSERT INTO语句-- 修复 SQLDELETEDELETE FROM db1.orders WHERE id 1001 AND order_no ORD-20260101;-- 回滚 SQLINSERTINSERT INTO db1.orders(id,order_no) VALUES(1001,ORD-20260101);对于有LIMIT子句的 DELETE无主键表场景回滚生成器会先剥离LIMIT再提取 WHERE 条件中的列值对。INSERT → DELETE 的转换过程修复 SQL 中的INSERT语句包含列名和值的完整映射。回滚生成器解析列名和值列表仅使用主键列或唯一键列构建DELETE的WHERE条件-- 修复 SQLINSERTINSERT INTO db1.orders(id,order_no,amount) VALUES(1001,ORD-20260101,99.50);-- 回滚 SQLDELETE仅使用 PK 列 idDELETE FROM db1.orders WHERE id 1001;NULL 值的特殊处理在 WHERE 条件中NULL值不能用 NULL表达回滚生成器会自动转换为IS NULL-- 修复 SQLDELETE FROM db1.users WHERE id 500 AND email IS NULL;-- 回滚 SQLINSERT INTO db1.users(id,email) VALUES(500,NULL);2.3 TRUNCATE 回滚整表为空时的特殊处理当目标端表在校验开始前整表为空行数为 0时修复 SQL 会是大量INSERT语句。如果逐行生成回滚 DELETE文件会非常大。此时 gt-checksum 采用一种更高效的策略生成单条TRUNCATE TABLE回滚语句忽略maxRollRowNum参数限制。关键安全约束只有校验开始前已确认目标端整表为空精确COUNT(*)为 0时才会生成 TRUNCATE 回滚。程序不会因为某个 chunk 的目标端为空就推断整张表为空——否则目标端非空但恰好某个 chunk 无数据时会误生成整表 TRUNCATE回滚这将导致回滚时丢失目标端原有的有效数据。同时当 TRUNCATE 回滚已生成后后续的逐行 INSERT 修复对应的回滚 DELETE 会被抑制避免回滚时先 TRUNCATE 再逐行 DELETE 的重复操作。⚠️重要提醒TRUNCATE 属于 DDL 操作执行时会隐式提交当前事务。使用 TRUNCATE 回滚 SQL 前需人工评估其影响。2.4 回滚 SQL 文件的生成与管理文件存储结构回滚 SQL 文件统一存储在rollFileDir目录默认rollsql下文件命名规则为rollsql/table.{schema}.{table}.rollback-{TYPE}-{seq}.sql其中{TYPE}为INSERT、DELETE或TRUNCATE{seq}为文件序号。例如rollsql/table.db1.orders.rollback-INSERT-1.sqlrollsql/table.db1.orders.rollback-DELETE-1.sqlrollsql/table.db1.users.rollback-TRUNCATE-1.sql文件内容格式每个回滚 SQL 文件包含完整的事务边界和会话设置SET FOREIGN_KEY_CHECKS0;SET UNIQUE_CHECKS0;BEGIN;DELETE FROM db1.orders WHERE id 1001;DELETE FROM db1.orders WHERE id 1002;COMMIT;BEGIN;DELETE FROM db1.orders WHERE id 1003;COMMIT;自动滚动切分当单个回滚 SQL 文件的语句数量或文件大小超过阈值由fixTrxNum和fixTrxSize参数控制时会自动创建新的文件。这确保了单个文件不会过大便于人工审计和分批执行。与 datafixtable 的配合关系当datafixtable在线修复模式时修复 SQL 会直接在目标端执行。但回滚 SQL始终只写文件不在线执行——这是刻意的安全设计。回滚 SQL 写入rollFileDir目录后需要人工审计确认无误再通过repairDB ./rollsql执行回滚。2.5 无主键表的 DELETE 合并优化对于没有主键和唯一键的表修复 SQL 中可能出现多条DELETE ... WHERE ... LIMIT 1语句其 WHERE 条件完全相同因为同一组值可能在目标端出现多次。gt-checksum 的回滚写入器内置了mergeDuplicateDeleteLimits优化-- 优化前3 条相同 WHERE 的 DELETEDELETE FROM db1.log_data WHERE ts 2026-01-01 AND msg test LIMIT 1;DELETE FROM db1.log_data WHERE ts 2026-01-01 AND msg test LIMIT 1;DELETE FROM db1.log_data WHERE ts 2026-01-01 AND msg test LIMIT 1;-- 优化后合并为 1 条LIMIT 累加DELETE FROM db1.log_data WHERE ts 2026-01-01 AND msg test LIMIT 3;这个优化仅在表无主键/唯一键时生效因为有主键表的每条 DELETE 的 WHERE 条件天然不同。2.6 与断点续传的配合当resumeON且任务中断后续传时回滚 SQL 的处理同样遵循安全原则续传开始时已有的回滚 SQL 文件会经过完整性截断定位到最后一个完整的COMMIT边界截断后续不完整的内容如果续传时某个表需要重新校验对应的旧回滚 SQL 文件会被清理后重新生成回滚文件的序号会从上次中断的位置继续不会覆盖已完整写入的文件2.7 回滚 SQL 的执行方式生成回滚 SQL 后需要人工审计确认无误然后通过repairDB工具执行# 审计回滚 SQL 文件ls -la rollsql/# 使用 repairDB 执行回滚repairDB ./rollsqlrepairDB 会自动识别目录中的 SQL 文件并按顺序执行支持断点续传——如果回滚执行过程中断再次运行会跳过已成功的文件。三、功能使用演示3.1 基本配置在配置文件gc.conf中设置相关参数# 开启回滚 SQL 生成genRollSQLONrollFileDirrollsqlmaxRollRowNum10000# 其他必要参数checkObjectdatadatafixfiletablesdb1.*srcDSNuser:ENC[...]tcp(10.0.0.1:3306)/db1dstDSNuser:ENC[...]tcp(10.0.0.2:3306)/db1chunkSize100003.2 运行效果$ gt-checksum -c gc.confInitializing gt-checksumReading configuration files...[CHECK] db1.orders: checksum mismatch in chunk 0-10000[FIX] db1.orders: DELETE 3 rows, INSERT 5 rows[ROLL] db1.orders: Writing rollback SQL (DELETE5, INSERT3)[CHECK] db1.users: checksum mismatch in chunk 0-10000[FIX] db1.users: DELETE 1 row, INSERT 0 rows[ROLL] db1.users: Writing rollback SQL (DELETE0, INSERT1)...校验完成后查看回滚 SQL 目录$ ls -la rollsql/total 24drwxr-xr-x 2 user user 4096 Jun 15 10:30 .drwxr-xr-x 6 user user 4096 Jun 15 10:30 ..-rw-r--r-- 1 user user 1256 Jun 15 10:30 table.db1.orders.rollback-DELETE-1.sql-rw-r--r-- 1 user user 856 Jun 15 10:30 table.db1.orders.rollback-INSERT-1.sql-rw-r--r-- 1 user user 312 Jun 15 10:30 table.db1.users.rollback-INSERT-1.sql查看回滚 SQL 内容$ cat rollsql/table.db1.orders.rollback-INSERT-1.sqlSET FOREIGN_KEY_CHECKS0;SET UNIQUE_CHECKS0;BEGIN;INSERT INTO db1.orders(id,order_no,amount) VALUES(1001,ORD-20260101,99.50);INSERT INTO db1.orders(id,order_no,amount) VALUES(1002,ORD-20260102,150.00);COMMIT;3.3 仅对指定表生成回滚 SQL如果只需要对特定表生成回滚 SQL可以使用自定义表名模式genRollSQLdb1.orders, db1.user%这将仅为db1.orders和db1.user开头的表生成回滚 SQL其他表不生成。支持%通配符匹配任意字符序列。3.4 执行回滚确认需要回退时使用 repairDB 执行回滚 SQL$ repairDB ./rollsql[REPAIR] Processing: table.db1.orders.rollback-INSERT-1.sql ... OK[REPAIR] Processing: table.db1.orders.rollback-DELETE-1.sql ... OK[REPAIR] Processing: table.db1.users.rollback-INSERT-1.sql ... OKRollback completed: 3 files executed successfully3.5 目标端整表为空场景的 TRUNCATE 回滚当目标端表在校验开始前为空时例如从零开始的数据迁移验收回滚 SQL 会生成单条TRUNCATE TABLE$ cat rollsql/table.db1.orders.rollback-TRUNCATE-1.sqlSET FOREIGN_KEY_CHECKS0;SET UNIQUE_CHECKS0;BEGIN;TRUNCATE TABLE db1.orders;COMMIT;此时不会为该表生成逐行 DELETE 的回滚文件因为 TRUNCATE 已经足以清空整张表。四、最佳实践及使用约束4.1 最佳实践1. 生产环境建议开启回滚 SQL对于数据修复任务无论使用datafixfile导出修复 SQL 文件还是datafixtable在线修复都建议开启genRollSQLON。回滚 SQL 的生成开销很小但在紧急回退场景下价值巨大genRollSQLONrollFileDirrollsql2. 大表场景适当调整 maxRollRowNummaxRollRowNum用于控制单表待修复行数的回滚阈值。默认值 10000 适用于大多数场景。如果表很大但仍然需要回滚保障可以调高该值# 允许单表最多 50000 行差异时也生成回滚 SQLmaxRollRowNum50000注意maxRollRowNum对 TRUNCATE 回滚不生效——目标端整表为空时始终生成 TRUNCATE 回滚。3. 仅对关键表生成回滚 SQL如果不需要对所有表生成回滚 SQL例如只关心核心业务表使用自定义表名模式减少文件量genRollSQLdb.orders, db.user%, db.account%4. 回滚 SQL 执行前务必人工审计回滚 SQL 始终只写文件、不在线执行。执行前请# 1. 查看生成了哪些回滚文件ls -la rollsql/# 2. 检查关键表的回滚内容cat rollsql/table.db.orders.rollback-*.sql# 3. 确认无误后使用 repairDB 执行repairDB ./rollsql5. 回滚后重新校验执行回滚后建议重新运行一次校验确认数据已恢复到修复前的状态# 先清空旧的回滚目录因为这次不需要回滚了rm -rf rollsql/# 重新校验gt-checksum -c gc.conf6. 结合 resume 使用时注意回滚文件累积断点续传模式下续传时旧的回滚文件会被安全截断或清理后重新生成。但如果多次中断-续传可能会产生较多的回滚文件。建议在任务正常完成后整理回滚目录保留最终版本即可。4.2 使用约束1. 仅适用于数据校验模式回滚 SQL 生成仅在checkObjectdata模式下生效。struct结构校验、trigger触发器校验、routine存储过程/函数校验不支持回滚 SQL 生成。2. 必须配合 datafixfile 或 datafixtable只有当datafix设置为file或table时回滚 SQL 才会被生成。datafixnone仅校验不修复模式下不会生成回滚 SQL因为没有修复操作也就不需要回退。3. rollFileDir 目录非空时的行为resumeOFF模式如果rollFileDir目录已存在且非空程序会报错退出避免覆盖旧的回滚文件resumeON/ASK模式允许目录非空续传逻辑会处理已有文件截断或清理4. 无主键表的回滚 INSERT 精度限制对于没有主键和唯一键的表回滚 INSERT 仅能基于修复 DELETE 的 WHERE 条件中可用的列值对可能无法完全还原原始行的所有列值如果 DELETE 语句的 WHERE 条件不包含所有列。5. TRUNCATE 回滚的 DDL 隐式提交风险TRUNCATE TABLE是 DDL 操作执行时会隐式提交当前事务并释放表锁。在使用 TRUNCATE 回滚 SQL 时需确认该行为不会对业务产生意外影响。建议在业务低峰期执行回滚操作。6. 配置一致性回滚 SQL 的目标端表名基于校验时的表映射规则。如果校验和回滚之间修改了表映射配置如srcdb.*:dstdb.*可能导致回滚 SQL 中的表名与实际表名不匹配。五、总结gt-checksum v4.0.0 的反向回滚 SQL 生成能力从根本上解决了数据修复单向执行、无法回退的痛点。通过genRollSQL一键开启每条修复 SQL 都会自动生成对应的反向操作写入结构化的回滚文件中。针对不同场景回滚机制做了精细化设计有主键表DELETE → INSERT全列还原INSERT → DELETEPK 定位删除无主键表自动合并重复 DELETE LIMIT回滚 INSERT 基于 WHERE 条件还原整表为空生成 TRUNCATE TABLE 回滚高效且不遗漏回滚 SQL 始终只写文件、不在线执行配合repairDB ./rollsql即可快速回退。整个过程可审计、可控制满足生产环境的安全合规要求。一句话总结genRollSQLON让每一次修复都有后悔药。