pt-show-grants 不能备份特定用户权限,它仅实时生成当前用户的 grant 语句,不包含 create user、不保证执行顺序、忽略 proxy/列级权限,且依赖用户存在和连接可用。

pt-show-grants 不能直接备份特定用户权限
pt-show-grants 是 Percona Toolkit 中的工具,它不“备份”权限,而是实时生成当前用户的 GRANT 语句。它本质是执行 SHOW GRANTS FOR 'u'@'h' 并格式化输出,没有存储、快照或导出文件能力。你运行它时看到的语句,就是此刻 MySQL 权限缓存里的内容——如果用户刚被删掉,pt-show-grants 就会报错 ERROR 1396 (HY000): Operation ALTER USER failed for 'u'@'h' 或直接跳过。
想只备份某个用户?别用 pt-show-grants 做主流程
真正可控、可审计、可回滚的做法是手动构造查询,精准命中目标用户:
- 用
SELECT CONCAT('SHOW GRANTS FOR ''', user, '''@''', host, ''';') FROM mysql.user WHERE user = 'myapp' AND host IN ('localhost', '%');生成对应SHOW GRANTS命令 - 再用管道捕获结果:
mysql -Nse "上面那条SELECT" | xargs -I{} mysql -Nse "{}" | sed 's/$/;/g' > myapp_grants.sql - MySQL 8.0+ 用户若用了角色,必须额外补查:
SELECT CONCAT('SET DEFAULT ROLE ', role, ' TO ''', user, '''@''', host, ''';') FROM mysql.role_edges JOIN mysql.default_roles USING (role, host) WHERE user = 'myapp'; - 注意:
pt-show-grants --user=myapp只能查到该用户存在且有登录权限时的结果;如果账号被锁、插件失效(如caching_sha2_password对应的 public key 不匹配),它连连接都建立不了
为什么有人误以为 pt-show-grants 能“备份”?
因为它的输出看起来像可执行 SQL,容易让人当成备份文件直接 source 回去。但问题在于:
- 它不包含
CREATE USER语句——恢复前必须确保用户已存在,否则GRANT会报错ERROR 1396 - 它不处理依赖顺序:比如先
GRANT再CREATE ROLE就会失败;而pt-show-grants默认按字母序输出,不保证逻辑先后 - 它默认忽略
PROXY权限和列级权限(COLUMNS_PRIV),除非显式加--all,但加了又可能拉进无关用户 - 输出里带反斜杠转义(如
'user\@host'),直接 source 可能语法错误;需用--no-quote-names或后处理
真正安全的“特定用户权限回滚”操作链
不是靠一个工具,而是组合动作:
- 备份前先确认用户状态:
SELECT user,host,account_locked,plugin,authentication_string IS NOT NULL FROM mysql.user WHERE user = 'myapp'; - 导出含
CREATE USER的完整授权块:用mysqldump --no-create-info --skip-triggers --skip-routines mysql user db tables_priv WHERE user='myapp'不现实,应改用自定义 SELECT 拼接 - 关键字段要过滤:
authentication_string和password_last_changed必须从输出中sed或awk删掉,避免备份泄露哈希值 - 恢复时必须分两步:
mysql -e "CREATE USER IF NOT EXISTS ... IDENTIFIED WITH ...;"→source myapp_grants.sql→FLUSH PRIVILEGES; - 最后验证:
mysql -u myapp -p -e "SELECT USER(), CURRENT_USER();"看是否真能登录、匹配预期 host
最易被忽略的是 FLUSH PRIVILEGES ——哪怕 SQL 全执行成功,不刷新权限缓存,新设置也不会生效。这不是可选步骤,是强制收尾动作。











