在数据校验和修复场景中,权限不足是最容易被误判的问题之一:看不到表,究竟是表不存在,还是当前账号没权限?
gt-checksum v4.0.0 完善了权限预检与修复安全策略,区分源端/目标端角色,按实际场景检查最小权限,并在目标端表不可见时优先提示权限不足,避免误生成危险的修复 SQL。
一、功能简介
v4.0.0 对权限预检和修复安全策略做了一次系统性增强,核心目标是:更符合最小权限原则、更容易排查权限问题、更安全地处理在线修复。
主要变化如下:
| 能力 | 说明 |
|---|---|
| 源端/目标端角色区分 | 源端只检查读取权限,目标端根据 checkObject 和 datafix 检查实际修复所需权限 |
| 通配/映射规则压缩检查 | 支持 db.*、db.t%、srcdb.*:dstdb.* 按源端/目标端角色压缩权限检查目标 |
| 空匹配权限提示 | 指定库表不可见或匹配为空时,提示检查权限,并给出 SHOW GRANTS / GRANT SELECT 建议 |
| 目标端不可见保护 | 目标端表元数据不可见时,先提示权限不足,不再直接当作缺表生成建表修复 SQL |
| 非 data 对象保守修复 | struct / routine / trigger 即使配置 datafix=table,也强制导出 fix SQL,不直接在线修改目标对象 |
这次变化不是简单增加几条权限检查,而是让权限预检逻辑真正理解“源端”和“目标端”的职责差异。
二、功能作用及使用场景深入解读
2.1 为什么需要重新设计权限预检?
在 v3.x 或更早版本中,权限检查容易出现两类问题:
问题一:权限要求过高
源端通常只是被读取的一方,按最小权限原则,只需要读取元数据和数据的权限。但如果源端也被要求具备 INSERT、DELETE、ALTER 等修复权限,就会增加授权成本,也不符合生产环境的安全规范。
问题二:权限不足被误判为对象不存在
MySQL 的 information_schema 查询结果受权限影响。如果当前账号没有权限查看某张表,这张表可能不会出现在元数据查询结果中。此时工具如果直接判断“目标端缺表”,就可能误生成 CREATE TABLE 修复 SQL,导致目标端数据被覆盖或结构被破坏。
问题三:非 data 对象在线修复风险高
checkObject=struct / routine / trigger 涉及 DDL、存储过程、触发器等对象变更。如果配置了 datafix=table 就直接在线修改目标端对象,风险远高于普通数据行修复。
因此,v4.0.0 的策略是:
源端尽量只读,目标端按需检查;对象不可见先怀疑权限,不轻易当作不存在;非 data 对象只导出 SQL,不直接在线执行。
2.2 源端/目标端角色区分:最小权限原则
v4.0.0 在权限预检接口中引入了 accessRole 概念,明确区分 source 和 dest。同样是 checkObject=data,源端和目标端需要的权限不同。
MySQL-family 权限矩阵:
| 场景 | 源端所需权限 | 目标端所需权限 |
|---|---|---|
checkObject=data, datafix=file | SELECT | SELECT |
checkObject=data, datafix=table | SELECT | SELECT、INSERT、DELETE |
checkObject=struct, datafix=file | SELECT | SELECT |
checkObject=struct, datafix=table | SELECT | SELECT、ALTER(预检结构修复权限) |
checkObject=trigger | TRIGGER | TRIGGER |
checkObject=routine | 按 MySQL 版本检查例程定义可见性 | 按 MySQL 版本检查例程定义可见性 |
其中一个重要修正是:
普通
checkObject=data数据校验不再强制要求未实际使用的REPLICATION CLIENT权限;datafix=table时 MySQL 目标端也不再误要求ALTER权限。
2.3 Oracle 权限也按角色区分
Oracle 场景下同样区分源端和目标端角色:
| 场景 | 源端所需权限 | 目标端所需权限 |
|---|---|---|
checkObject=data, datafix=file | SELECT ANY TABLE 或对象级 SELECT | SELECT ANY TABLE 或对象级 SELECT |
checkObject=data, datafix=table | SELECT ANY TABLE 或对象级 SELECT | SELECT ANY TABLE、INSERT ANY TABLE、DELETE ANY TABLE,或对象级等价权限 |
checkObject=struct, datafix=table | SELECT ANY TABLE 或对象级 SELECT | 结构修复相关 ALTER 权限 |
这对 Oracle → MySQL 异构迁移尤其重要:源端 Oracle 账号通常由业务系统或第三方提供,能授予只读权限就不应要求写权限。
2.4 通配与映射规则压缩检查
gt-checksum 支持多种表选择方式:
tables=db.*
tables=db.t%
tables=srcdb.*:dstdb.*
tables=srcdb.orders:dstdb.orders_new
v4.0.0 在权限预检中会保留原始 tables 规则,并按源端/目标端角色压缩检查目标。
示例一:普通通配
tables=sbtest.*
如果元数据展开后有 sbtest.t1、sbtest.t2、sbtest.t3,权限检查不会机械地逐表检查三次,而是压缩为:
sbtest.*
如果账号拥有 GRANT SELECT ON sbtest.*,就可以覆盖该库下所有表。
示例二:源端到目标端映射
tables=srcdb.*:dstdb.*
权限预检会按角色拆开:
| 角色 | 检查目标 |
|---|---|
| 源端 | srcdb.* |
| 目标端 | dstdb.* |
这避免了用源端库名去检查目标端权限,或者用目标端库名去检查源端权限的混淆问题。
示例三:部分通配
tables=db.order%
% 用于表名部分通配。v4.0.0 会在权限提示中尽量归并为库级授权建议,例如:
GRANT SELECT ON `db`.* TO '<source_user>'@'<host>';
注意:表名部分通配请使用
%,不要使用*。db.*表示整库所有表是合法的,但db.t*这类写法会被提示改为db.t%。
2.5 指定库表不可见或匹配为空时给出授权建议
过去当 tables=sbtest.* 匹配不到任何表时,用户往往只能看到类似 No tables to check 的提示,但不知道到底是:
- 表真的不存在?
tables配置写错?- 当前账号没有权限看见这些表?
v4.0.0 对这种场景增加了更明确的权限排查提示。
当源端元数据为空,或源端元数据非空但指定库表匹配不到时,日志会提示:
current source user may lack SELECT privilege
SHOW GRANTS FOR CURRENT_USER();
SHOW GRANTS FOR '<user>'@'<host>';
并给出类似下面的授权建议:
GRANT SELECT ON `sbtest`.* TO '<source_user>'@'<host>';
终端层面也会给出更清晰的提示:
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 logLevel=debug
这样用户可以第一时间从日志中获取可执行的排查方向,而不是盲目修改 tables 配置。
2.6 目标端表不可见:先提示权限不足,不误判为缺表
这是 v4.0.0 权限预检中非常关键的一项安全修复。
假设配置如下:
checkObject=struct
datafix=file
tables=db.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 logLevel=debug
日志中会进一步说明:
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 checkObject=data 的表存在性不一致处理
在 checkObject=data 模式下,如果源端或目标端表缺失,v4.0.0 不会继续做数据校验,也不会在 data 模式中直接生成结构修复 SQL,而是记录为 DDL 差异:
DIFFS = DDL-yes
Rows = table missing on target / table missing on source / table missing on both source and target
并提示用户使用:
checkObject=struct
重新检查并修复表结构。
这让 data 模式职责更清晰:data 模式只处理数据差异,结构缺失交给 struct 模式。
2.8 routine 权限预检按 MySQL 版本给建议
MySQL 不同版本读取存储过程/函数定义所需权限并不完全相同。v4.0.0 对 checkObject=routine 做了版本化授权提示:
| MySQL 版本 | 例程定义读取建议 |
|---|---|
| MySQL 8.0.20+ | SHOW_ROUTINE 或全局 SELECT |
| MySQL 8.0.0 - 8.0.19 | 全局 SELECT |
| MySQL 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 对象:datafix=table 也强制导出 SQL
v4.0.0 的另一个重要安全策略是:
checkObject=struct/routine/trigger即使配置了datafix=table,也不会直接在线修改目标对象,而是强制导出 fix SQL 文件,供人工审核后再执行。
例如:
checkObject=struct
datafix=table
fixFileDir=fixsql
启动时会提示:
gt-checksum: [WARN] checkObject=struct with datafix=table does not directly repair target objects; force exporting fix SQL file to fixsql for manual review
运行时也会记录日志:
checkObject=struct with datafix=table does not directly repair target objects; force exporting fix SQL file for manual review.
这意味着结构、例程、触发器等对象修复都进入“先导出、再审核、后执行”的保守流程,避免 DDL 或对象定义在未审核情况下直接在线变更。
三、功能使用演示
3.1 源端只读、目标端在线修复授权
对于普通数据校验并在线修复:
checkObject=data
datafix=table
tables=db.*
推荐授权方式:
-- 源端:只读
GRANT SELECT ON `db`.* TO 'checksum_src'@'%';
-- 目标端:读取 + 数据修复
GRANT SELECT, INSERT, DELETE ON `db`.* TO 'checksum_dst'@'%';
不需要给源端 INSERT / DELETE / ALTER,也不需要在 data 模式下给目标端 ALTER。
3.2 通配规则权限预检
配置:
tables=sbtest.*
checkObject=data
datafix=file
如果当前源端账号没有权限读取 sbtest 库,日志会提示:
current source user may lack SELECT privilege on the selected schema/table
SHOW GRANTS FOR CURRENT_USER();
SHOW GRANTS FOR '<user>'@'<host>';
suggested source GRANT examples: GRANT SELECT ON `sbtest`.* TO '<source_user>'@'<host>';
用户可以按提示检查当前账号授权:
SHOW GRANTS FOR CURRENT_USER();
并补充授权:
GRANT SELECT ON `sbtest`.* TO 'checksum_src'@'%';
3.3 映射规则权限预检
配置:
tables=srcdb.*:dstdb.*
checkObject=data
datafix=table
预期权限:
-- 源端检查 srcdb.*
GRANT SELECT ON `srcdb`.* TO 'checksum_src'@'%';
-- 目标端检查 dstdb.*
GRANT SELECT, INSERT, DELETE ON `dstdb`.* TO 'checksum_dst'@'%';
这类场景在跨库迁移中很常见,v4.0.0 会按源端/目标端角色分别压缩和检查,避免授权建议混用库名。
3.4 目标端表不可见时的保护
配置:
checkObject=struct
datafix=file
tables=db.orders
如果目标端账号没有权限查看 db.orders,运行结果不再是直接生成建表 SQL,而是终端提示:
gt-checksum: Insufficient access permission to target table. Check gt-checksum.log for details or set logLevel=debug
此时应先检查目标端授权:
SHOW GRANTS FOR CURRENT_USER();
并补充必要权限后重新执行。
3.5 非 data 对象强制导出 fix SQL
配置:
checkObject=struct
datafix=table
fixFileDir=fixsql
即使设置了 datafix=table,gt-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 模式授权
如果只生成修复 SQL:
datafix=file
目标端通常只需要 SELECT 权限。
如果在线修复数据:
datafix=table
checkObject=data
目标端需要:
GRANT SELECT, INSERT, DELETE ON `db`.* TO 'checksum_dst'@'%';
3. 遇到 No tables to check 先看日志授权建议
不要只检查 tables 配置,也要检查当前账号是否能看见指定库表:
SHOW GRANTS FOR CURRENT_USER();
日志中的 GRANT SELECT 建议通常能直接定位缺失授权。
4. 使用映射规则时分别检查源端和目标端授权
例如:
tables=srcdb.*:dstdb.*
不要只给 srcdb.* 授权,也要确认目标端账号拥有 dstdb.* 的相应权限。
5. 非 data 对象坚持人工审核
结构、例程、触发器变更建议始终走:
导出 fix SQL → 人工审核 → repairDB 或手工执行 → 重新校验
不要期望 checkObject=struct/routine/trigger + datafix=table 直接在线修改目标对象。
6. routine / trigger 场景提前确认版本与权限
不同 MySQL / MariaDB 版本读取 routine 定义的权限差异较大。执行前建议先确认版本,并按日志提示补充 SHOW_ROUTINE、全局 SELECT 或 mysql.proc 读取权限。
4.2 使用约束
1. 权限预检依赖当前账号可见的元数据
MySQL 的元数据可见性受权限影响。即使对象真实存在,当前账号没有权限时也可能查询不到。因此 v4.0.0 会优先提示权限不足,但最终仍需要 DBA 根据实际对象和授权情况确认。
2. db.t* 不是合法的部分通配写法
表名部分通配请使用 %:
# 推荐
tables=db.t%
# 不推荐/会被提示修正
tables=db.t*
只有 db.* 这种整库所有表写法中的 * 是合法的。
3. data 模式不负责结构修复
checkObject=data 发现源端或目标端表缺失时,会标记为 DDL-yes 并跳过数据校验。需要修复表结构时,应切换到:
checkObject=struct
4. 目标端表不可见不会被当作缺表自动修复
如果目标端表元数据不可见且权限不足,程序会拒绝生成缺表修复 SQL。必须先补齐目标端权限,再重新执行。
5. datafix=table 不代表所有对象都在线修复
v4.0.0 中,只有 checkObject=data 的数据差异才允许在线修复。struct / routine / trigger 即使配置 datafix=table,也会强制导出 fix SQL。
6. 授权建议是参考模板,不会自动执行
日志中的 GRANT 语句用于排查和参考,不会由 gt-checksum 自动执行。实际授权仍需 DBA 根据安全策略、账号范围和主机来源调整后执行。
五、总结
gt-checksum v4.0.0 的权限预检与修复安全策略升级,从“能不能跑”进一步提升到“是否以正确、安全、最小权限的方式运行”。
这次增强带来的价值包括:
- 源端/目标端权限职责清晰,符合最小权限原则;
- 通配与映射规则按角色压缩检查,授权建议更准确;
- 指定库表不可见或匹配为空时,给出
SHOW GRANTS/GRANT SELECT排查路径; - 目标端表不可见时优先提示权限不足,避免误判缺表并生成危险修复 SQL;
- 非 data 对象不再直接在线修复,统一导出 SQL 供人工审核。
一句话总结:先确认账号“看得见、权限够”,再决定数据怎么校验、对象怎么修复。
相关阅读
- gt-checksum v4.0.0 新功能解读系列文章(1):断点续传——大任务中断不再从头跑
- gt-checksum v4.0.0 新功能解读系列文章(2):自定义数据类型映射——适配复杂迁移场景
- gt-checksum v4.0.0 新功能解读系列文章(3):反向回滚 SQL——修复可审计、可回退
- gt-checksum v4.0.0 新功能解读系列文章(4):反向回滚 SQL——修复可审计、可回退
- gt-checksum v4.0.0 新功能解读系列文章(5):反向回滚 SQL——修复可审计、可回退
- gt-checksum v4.0.0 发布:可续跑、可回滚、可审计的数据校验与修复能力全面升级
- gt-checksum 使用手册
:权限预检与修复安全策略——先确认能看见,再决定怎么修&spm=1001.2101.3001.5002&articleId=162259261&d=1&t=3&u=c9bfab5e57d046d189d6808c0c6e30af)
335

被折叠的 条评论
为什么被折叠?



