gt-checksum v4.0.0 新功能解读系列文章(6):权限预检与修复安全策略——先确认能看见,再决定怎么修 、功能简介v4.0.0 对权限预检和修复安全策略做了一次系统性增强核心目标是更符合最小权限原则、更容易排查权限问题、更安全地处理在线修复。主要变化如下能力说明源端/目标端角色区分源端只检查读取权限目标端根据checkObject和datafix检查实际修复所需权限通配/映射规则压缩检查支持db.*、db.t%、srcdb.*:dstdb.*按源端/目标端角色压缩权限检查目标空匹配权限提示指定库表不可见或匹配为空时提示检查权限并给出SHOW GRANTS/GRANT SELECT建议目标端不可见保护目标端表元数据不可见时先提示权限不足不再直接当作缺表生成建表修复 SQL非 data 对象保守修复struct/routine/trigger即使配置datafixtable也强制导出 fix SQL不直接在线修改目标对象这次变化不是简单增加几条权限检查而是让权限预检逻辑真正理解“源端”和“目标端”的职责差异。二、功能作用及使用场景深入解读2.1 为什么需要重新设计权限预检在 v3.x 或更早版本中权限检查容易出现两类问题问题一权限要求过高源端通常只是被读取的一方按最小权限原则只需要读取元数据和数据的权限。但如果源端也被要求具备INSERT、DELETE、ALTER等修复权限就会增加授权成本也不符合生产环境的安全规范。问题二权限不足被误判为对象不存在MySQL 的information_schema查询结果受权限影响。如果当前账号没有权限查看某张表这张表可能不会出现在元数据查询结果中。此时工具如果直接判断“目标端缺表”就可能误生成 CREATE TABLE 修复 SQL导致目标端数据被覆盖或结构被破坏。问题三非 data 对象在线修复风险高checkObjectstruct/routine/trigger涉及 DDL、存储过程、触发器等对象变更。如果配置了datafixtable就直接在线修改目标端对象风险远高于普通数据行修复。因此v4.0.0 的策略是源端尽量只读目标端按需检查对象不可见先怀疑权限不轻易当作不存在非 data 对象只导出 SQL不直接在线执行。2.2 源端/目标端角色区分最小权限原则v4.0.0 在权限预检接口中引入了accessRole概念明确区分source和dest。同样是checkObjectdata源端和目标端需要的权限不同。MySQL-family 权限矩阵场景源端所需权限目标端所需权限checkObjectdata, datafixfileSELECTSELECTcheckObjectdata, datafixtableSELECTSELECT、INSERT、DELETEcheckObjectstruct, datafixfileSELECTSELECTcheckObjectstruct, datafixtableSELECTSELECT、ALTER预检结构修复权限checkObjecttriggerTRIGGERTRIGGERcheckObjectroutine按 MySQL 版本检查例程定义可见性按 MySQL 版本检查例程定义可见性其中一个重要修正是普通checkObjectdata数据校验不再强制要求未实际使用的REPLICATION CLIENT权限datafixtable时 MySQL 目标端也不再误要求ALTER权限。2.3 Oracle 权限也按角色区分Oracle 场景下同样区分源端和目标端角色场景源端所需权限目标端所需权限checkObjectdata, datafixfileSELECT ANY TABLE或对象级SELECTSELECT ANY TABLE或对象级SELECTcheckObjectdata, datafixtableSELECT ANY TABLE或对象级SELECTSELECT ANY TABLE、INSERT ANY TABLE、DELETE ANY TABLE或对象级等价权限checkObjectstruct, datafixtableSELECT ANY TABLE或对象级SELECT结构修复相关ALTER权限这对 Oracle → MySQL 异构迁移尤其重要源端 Oracle 账号通常由业务系统或第三方提供能授予只读权限就不应要求写权限。2.4 通配与映射规则压缩检查gt-checksum 支持多种表选择方式tablesdb.*tablesdb.t%tablessrcdb.*:dstdb.*tablessrcdb.orders:dstdb.orders_newv4.0.0 在权限预检中会保留原始tables规则并按源端/目标端角色压缩检查目标。示例一普通通配tablessbtest.*如果元数据展开后有sbtest.t1、sbtest.t2、sbtest.t3权限检查不会机械地逐表检查三次而是压缩为sbtest.*如果账号拥有GRANT SELECT ON sbtest.*就可以覆盖该库下所有表。示例二源端到目标端映射tablessrcdb.*:dstdb.*权限预检会按角色拆开角色检查目标源端srcdb.*目标端dstdb.*这避免了用源端库名去检查目标端权限或者用目标端库名去检查源端权限的混淆问题。示例三部分通配tablesdb.order%%用于表名部分通配。v4.0.0 会在权限提示中尽量归并为库级授权建议例如GRANT SELECT ON db.* TO source_userhost;注意表名部分通配请使用%不要使用*。db.*表示整库所有表是合法的但db.t*这类写法会被提示改为db.t%。2.5 指定库表不可见或匹配为空时给出授权建议过去当tablessbtest.*匹配不到任何表时用户往往只能看到类似No tables to check的提示但不知道到底是表真的不存在tables配置写错当前账号没有权限看见这些表v4.0.0 对这种场景增加了更明确的权限排查提示。当源端元数据为空或源端元数据非空但指定库表匹配不到时日志会提示current source user may lack SELECT privilegeSHOW GRANTS FOR CURRENT_USER();SHOW GRANTS FOR userhost;并给出类似下面的授权建议GRANT SELECT ON sbtest.* TO source_userhost;终端层面也会给出更清晰的提示gt-checksum: No tables to check. Check whether tables is correct, whether the selected objects exist, and whether the current DB user has privileges on them. See gt-checksum.log for SHOW GRANTS / GRANT SELECT suggestions or set logLeveldebug这样用户可以第一时间从日志中获取可执行的排查方向而不是盲目修改tables配置。2.6 目标端表不可见先提示权限不足不误判为缺表这是 v4.0.0 权限预检中非常关键的一项安全修复。假设配置如下checkObjectstructdatafixfiletablesdb.orders源端表db.orders存在但目标端账号没有权限查看目标端同名表。此时目标端元数据查询可能返回“表不存在”。如果直接当作缺表处理工具可能生成CREATE TABLE IF NOT EXISTS db.orders (...);但实际上目标端表可能已经存在只是当前账号看不见。这类修复 SQL 显然是不安全的。v4.0.0 的处理方式是当发现源端存在、目标端元数据不可见时先执行目标端权限预检如果目标端账号缺少必要权限则拒绝把它当作缺表终端提示gt-checksum: Insufficient access permission to target table. Check gt-checksum.log for details or set logLeveldebug日志中会进一步说明Target table db.orders is not visible in metadata and target user lacks required privileges ... Refuse to treat it as missing; please grant target table privileges and retry.这可以避免“目标端表不可见 → 误判缺表 → 生成错误建表修复 SQL”的连锁风险。2.7 checkObjectdata 的表存在性不一致处理在checkObjectdata模式下如果源端或目标端表缺失v4.0.0 不会继续做数据校验也不会在 data 模式中直接生成结构修复 SQL而是记录为 DDL 差异DIFFS DDL-yesRows table missing on target / table missing on source / table missing on both source and target并提示用户使用checkObjectstruct重新检查并修复表结构。这让 data 模式职责更清晰data 模式只处理数据差异结构缺失交给 struct 模式。2.8 routine 权限预检按 MySQL 版本给建议MySQL 不同版本读取存储过程/函数定义所需权限并不完全相同。v4.0.0 对checkObjectroutine做了版本化授权提示MySQL 版本例程定义读取建议MySQL 8.0.20SHOW_ROUTINE或全局SELECTMySQL 8.0.0 - 8.0.19全局SELECTMySQL 5.6 / 5.7、MariaDB例程 definer或SELECT ON mysql.proc/SELECT ON mysql.*例如 MySQL 8.0.20 场景中日志会给出类似建议GRANT SHOW_ROUTINE ON *.* TO user%;MySQL 5.7 / MariaDB 场景中则可能建议GRANT SELECT ON mysql.proc TO user%;这比单纯提示“权限不足”更容易落地。2.9 非 data 对象datafixtable 也强制导出 SQLv4.0.0 的另一个重要安全策略是checkObjectstruct/routine/trigger即使配置了datafixtable也不会直接在线修改目标对象而是强制导出 fix SQL 文件供人工审核后再执行。例如checkObjectstructdatafixtablefixFileDirfixsql启动时会提示gt-checksum: [WARN] checkObjectstruct with datafixtable does not directly repair target objects; force exporting fix SQL file to fixsql for manual review运行时也会记录日志checkObjectstruct with datafixtable does not directly repair target objects; force exporting fix SQL file for manual review.这意味着结构、例程、触发器等对象修复都进入“先导出、再审核、后执行”的保守流程避免 DDL 或对象定义在未审核情况下直接在线变更。三、功能使用演示3.1 源端只读、目标端在线修复授权对于普通数据校验并在线修复checkObjectdatadatafixtabletablesdb.*推荐授权方式-- 源端只读GRANT SELECT ON db.* TO checksum_src%;-- 目标端读取 数据修复GRANT SELECT, INSERT, DELETE ON db.* TO checksum_dst%;不需要给源端INSERT/DELETE/ALTER也不需要在 data 模式下给目标端ALTER。3.2 通配规则权限预检配置tablessbtest.*checkObjectdatadatafixfile如果当前源端账号没有权限读取sbtest库日志会提示current source user may lack SELECT privilege on the selected schema/tableSHOW GRANTS FOR CURRENT_USER();SHOW GRANTS FOR userhost;suggested source GRANT examples: GRANT SELECT ON sbtest.* TO source_userhost;用户可以按提示检查当前账号授权SHOW GRANTS FOR CURRENT_USER();并补充授权GRANT SELECT ON sbtest.* TO checksum_src%;3.3 映射规则权限预检配置tablessrcdb.*:dstdb.*checkObjectdatadatafixtable预期权限-- 源端检查 srcdb.*GRANT SELECT ON srcdb.* TO checksum_src%;-- 目标端检查 dstdb.*GRANT SELECT, INSERT, DELETE ON dstdb.* TO checksum_dst%;这类场景在跨库迁移中很常见v4.0.0 会按源端/目标端角色分别压缩和检查避免授权建议混用库名。3.4 目标端表不可见时的保护配置checkObjectstructdatafixfiletablesdb.orders如果目标端账号没有权限查看db.orders运行结果不再是直接生成建表 SQL而是终端提示gt-checksum: Insufficient access permission to target table. Check gt-checksum.log for details or set logLeveldebug此时应先检查目标端授权SHOW GRANTS FOR CURRENT_USER();并补充必要权限后重新执行。3.5 非 data 对象强制导出 fix SQL配置checkObjectstructdatafixtablefixFileDirfixsql即使设置了datafixtablegt-checksum 也不会直接在线执行结构修复而是导出fixsql/table.db.orders.sql用户需要人工审核cat fixsql/table.db.orders.sql确认无误后再使用 repairDB 或手工执行。四、最佳实践及使用约束4.1 最佳实践1. 源端账号坚持只读原则源端用于读取数据和元数据不应授予写入或 DDL 权限GRANT SELECT ON db.* TO checksum_src%;这既满足校验需要也降低误操作风险。2. 目标端按 datafix 模式授权如果只生成修复 SQLdatafixfile目标端通常只需要SELECT权限。如果在线修复数据datafixtablecheckObjectdata目标端需要GRANT SELECT, INSERT, DELETE ON db.* TO checksum_dst%;3. 遇到 No tables to check 先看日志授权建议不要只检查tables配置也要检查当前账号是否能看见指定库表SHOW GRANTS FOR CURRENT_USER();日志中的GRANT SELECT建议通常能直接定位缺失授权。4. 使用映射规则时分别检查源端和目标端授权例如tablessrcdb.*:dstdb.*不要只给srcdb.*授权也要确认目标端账号拥有dstdb.*的相应权限。5. 非 data 对象坚持人工审核结构、例程、触发器变更建议始终走导出 fix SQL → 人工审核 → repairDB 或手工执行 → 重新校验不要期望checkObjectstruct/routine/trigger datafixtable直接在线修改目标对象。6. routine / trigger 场景提前确认版本与权限不同 MySQL / MariaDB 版本读取 routine 定义的权限差异较大。执行前建议先确认版本并按日志提示补充SHOW_ROUTINE、全局SELECT或mysql.proc读取权限。4.2 使用约束1. 权限预检依赖当前账号可见的元数据MySQL 的元数据可见性受权限影响。即使对象真实存在当前账号没有权限时也可能查询不到。因此 v4.0.0 会优先提示权限不足但最终仍需要 DBA 根据实际对象和授权情况确认。2.db.t*不是合法的部分通配写法表名部分通配请使用%# 推荐tablesdb.t%# 不推荐/会被提示修正tablesdb.t*只有db.*这种整库所有表写法中的*是合法的。3. data 模式不负责结构修复checkObjectdata发现源端或目标端表缺失时会标记为DDL-yes并跳过数据校验。需要修复表结构时应切换到checkObjectstruct4. 目标端表不可见不会被当作缺表自动修复如果目标端表元数据不可见且权限不足程序会拒绝生成缺表修复 SQL。必须先补齐目标端权限再重新执行。5.datafixtable不代表所有对象都在线修复v4.0.0 中只有checkObjectdata的数据差异才允许在线修复。struct/routine/trigger即使配置datafixtable也会强制导出 fix SQL。6. 授权建议是参考模板不会自动执行日志中的GRANT语句用于排查和参考不会由 gt-checksum 自动执行。实际授权仍需 DBA 根据安全策略、账号范围和主机来源调整后执行。五、总结gt-checksum v4.0.0 的权限预检与修复安全策略升级从“能不能跑”进一步提升到“是否以正确、安全、最小权限的方式运行”。这次增强带来的价值包括源端/目标端权限职责清晰符合最小权限原则通配与映射规则按角色压缩检查授权建议更准确指定库表不可见或匹配为空时给出SHOW GRANTS/GRANT SELECT排查路径目标端表不可见时优先提示权限不足避免误判缺表并生成危险修复 SQL非 data 对象不再直接在线修复统一导出 SQL 供人工审核。一句话总结先确认账号“看得见、权限够”再决定数据怎么校验、对象怎么修复。