您现在的位置: 365建站网 > 365文章 > pt-show-grants 怎么批量导出 MySQL 所有用户权限?参数详解与迁移实操

pt-show-grants 怎么批量导出 MySQL 所有用户权限?参数详解与迁移实操

文章来源:365jz.com 点击数:12 更新时间:2026-02-13 09:58

做过数据库运维的人大概都有这种痛苦:新机房搭好了,要迁移几十个 MySQL 账号和它们的权限,手工对着 mysql.user 表敲 GRANT 语句不仅慢,还极易漏掉 WITH GRANT OPTION 这种细节。Percona Toolkit 里的 pt-show-grants 就是为这件事设计的——它把散落在系统表里的权限,反向生成成一份可执行、可读、可审计的 SQL。

pt-show-grants 批量导出 MySQL 用户权限脚本

一、为什么不直接查 mysql.user 或 mysqldump

三种常见思路的差别要说清楚:

  • SELECT * FROM mysql.user:拿到的是哈希后的认证串和字段矩阵,Select_priv='Y' 这种表示没法直接在新实例执行,还得人工翻译成 GRANT。
  • mysqldump --no-data --routines mysql:会导出整个权限表的数据行,跨版本恢复时经常因为字段缺失/新增报错(例如 5.7 的 password 列在 8.0 变成 authentication_string),风险高。
  • pt-show-grants:逐用户执行 SHOW GRANTS FOR ...,把结果按数据库分组排序后输出标准 GRANT ... IDENTIFIED BY PASSWORD '...' 语句,可以在目标库原样执行,也天然是审计材料。

工具属于 Percona Toolkit(官方仓库 https://docs.percona.com/percona-toolkit/ ),安装方式:CentOS/RHEL yum install percona-toolkit,Ubuntu/Debian apt install percona-toolkit,也可以直接下 tar 包用 perl 跑(依赖 DBI 与 DBD::mysql)。命令验证:pt-show-grants --version。

二、批量导出所有用户权限

最常用的一条:

pt-show-grants --user=root --ask-pass --flush > grants_$(date +%F).sql
  • --ask-pass 交互式输入密码,避免密码进 shell history;也可 --password='xxx'(不安全)或写 ~/.my.cnf。
  • --flush:在文件末尾追加 FLUSH PRIVILEGES;,让恢复脚本执行完立即生效。
  • 输出会自动跳过 root@localhost 一类你不想迁移的账号(可用 --ignore-user 精确控制)。
  • 默认按数据库名字母排序,保证 GRANT 的执行顺序稳定,重复运行产出可比对的相同文本,方便进 Git 做权限基线 diff。

只导出部分用户:--only user1,user2(正则可用 --regex);排除:--ignore-user 'repl|monitor'。

三、输出示例与含义解读

-- Grants for repl@10.0.%
GRANT REPLICATION SLAVE ON *.* TO `repl`@`10.0.%` IDENTIFIED BY PASSWORD '*6BBC...';
-- Grants for app@localhost
GRANT USAGE ON *.* TO `app`@`localhost`;
GRANT SELECT, INSERT, UPDATE, DELETE ON `shopdb`.* TO `app`@`localhost`;
GRANT SELECT ON `shopdb`.`orders` TO `app`@`localhost`;

三个细节值得注意:

  • USAGE ON *.* 不是“有权限”,它表示只有登录权限、没有任何库级权限,工具仍会输出,是为了让账号在新实例上先存在。
  • 库级、表级、列级权限被拆成多条语句,顺序是「全局 → 库 → 表 → 列」,必须整段一起执行才等价。
  • IDENTIFIED BY PASSWORD '*...' 带的是哈希串,导出文件等同于密码哈希,必须按机密文件管理(建议 chmod 600)。

四、MySQL 8.0 上的写法变化

8.0 起 GRANT 不再隐式创建用户,且认证插件默认 caching_sha2_password。实践中的处理:

  • 导出时加 --compat8(较新版本参数名可能写作 --compat80,用 pt-show-grants --help | grep -i compat 确认),工具会拆成 CREATE USER ... ; GRANT ...; 的形式。
  • 跨版本迁移建议显式指定插件:ALTER USER 'app'@'%' IDENTIFIED WITH mysql_native_password BY '...';,否则老客户端连不上。想全局默认,改 my.cnf 的 default_authentication_plugin。
  • 要顺带迁移角色:pt-show-grants 对 ROLE 支持有限,角色的 GRANT ... TO role 建议手工用 SELECT * FROM mysql.role_edges 复核。

五、权限的批量写入与回收

导出是读的活,写回去更要注意顺序:

  • 整库重建:mysql -u root -p < grants_2024-04-12.sql,执行前先备份现有:pt-show-grants > grants_before.sql。
  • 批量回收某类权限:把导出文件做正则处理。例如去掉所有 GRANT OPTION:sed -i 's/ WITH GRANT OPTION//g' grants.sql,再重新导入。这类“导出→改→导入”的循环比一条条 REVOKE 快得多,但一定要在测试库先跑一遍。
  • 生成审计报表:结合 SELECT user,host,DB,table_name,priv_type FROM mysql.tables_priv 与 columns_priv 做交叉核对,避免只见库权限、漏了列权限。

六、常见问题与替代方案

  • 报错 “Access denied; you need (at least one of) the ... privilege”:账号需要 SELECT ON mysql.*,MySQL 8.0 还需要 SHOW VIEW 与 RELOAD;或直接用 root。
  • “Distributed” 权限缺失 / 集群版:TiDB、MariaDB 集群语法有差异,导出脚本不一定能原样执行,务必逐条 review。
  • 不想装 Percona Toolkit:纯 SQL 方案是从 information_schema 拼语句,例如
    SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>'',把结果再交给 mysql 客户端执行,效果类似但排序、去重、兼容性都要自己补。
  • 与 pt-sync-grants / mysqldump 的取舍:只要权限语句,用 pt-show-grants;要连账号资源限制(max_user_connections)一起迁,则需额外处理 mysql.user 里的这些列,工具不会自动带上。

七、常见问题 FAQ

问:导出的文件能不能直接给开发用?
答:不能。里面含密码哈希与完整权限拓扑,属于敏感资产。脱敏办法是 sed -E "s/IDENTIFIED BY PASSWORD '[^']*'/IDENTIFIED BY PASSWORD 'REDACTED'/g" 之后再分享。

问:能不能只在主从之间同步权限?
答:可以,pt-show-grants -h 主库IP | mysql -h 从库IP -u root -p 一条管道完成,但生产建议中间落文件,保留一份可回滚的快照。

问:想定期备份权限怎么做?
答:加 cron:10 2 * * * /usr/bin/pt-show-grants --ask-pass --flush > /backup/mysql_grants/grants_$(date +\%F).sql(cron 里 % 必须转义为 \%,这是最常被忽略的细节),再配 7 天轮转删除。

一句话收尾:pt-show-grants 的价值不只是“少打字”,而是把权限变成可以版本化、可以 diff、可以整体重放的文本资产。养成每周导出一份基线的习惯,出问题时你才有回滚的底气。

生产内容,同时打通搜索引擎(SEO)与AI搜索引擎(GEO)流量入口的软件! 点击进入365建站器 »