不能直接 INSERT INTO mysql.db 修改权限,因为MySQL依赖内存缓存和字段语义(如authentication_string、plugin),且需FLUSH PRIVILEGES生效;手动操作易导致权限不生效、登录失败或越权。

直接复制 MySQL 用户的库表权限不能靠 INSERT INTO mysql.db 这类物理表操作,必须用逻辑导出还原方式——否则权限不生效、密码错乱、甚至引发越权或拒绝访问。
为什么不能直接 INSERT 权限表?
MySQL 5.7+ 的权限校验依赖内存缓存 + 字段语义(如 authentication_string、plugin),且 mysql.db 等表受内部机制保护:
- 直接写入
mysql.db后不执行FLUSH PRIVILEGES,权限不会加载进内存; - 即使执行了
FLUSH PRIVILEGES,若user表中对应用户不存在或plugin不匹配(如caching_sha2_passwordvsmysql_native_password),登录会失败; -
SHOW GRANTS输出的是授权逻辑,而mysql.db存储的是扁平化权限位(Select_priv、Insert_priv等),字段映射复杂,手动拼容易漏或错。
正确做法:用 SHOW GRANTS 生成可执行语句
这是最安全、兼容性最好、无需知道明文密码的方法。核心是把源库中用户的授权语句原样提取,在目标库重放:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 在源库执行:
SHOW GRANTS FOR 'app_user'@'10.20.%'; - 输出类似:
GRANT SELECT, INSERT ON `orders`.* TO 'app_user'@'10.20.%'; - 将所有
GRANT语句复制到目标库执行即可(注意:目标库必须已存在该用户)
如果用户还不存在,先补 CREATE USER:
- 查源库:
SELECT user, host, plugin, authentication_string FROM mysql.user WHERE user = 'app_user'; - 在目标库建用户:
CREATE USER 'app_user'@'10.20.%' IDENTIFIED WITH caching_sha2_password AS '$A$...'; - 再执行上面的
GRANT语句
批量迁移多个用户权限的实操要点
手动逐个 SHOW GRANTS 效率低,可用以下方式自动化,但要注意边界条件:
- 用
mysqldump导出权限表时,必须加--skip-lock-tables和显式指定表:mysqldump -u root -p --skip-lock-tables --databases mysql --tables user db tables_priv columns_priv > grants.sql; - 导入前,目标库需先清理同名用户:
DROP USER 'app_user'@'10.20.%';(避免权限叠加); - 导入后必须执行
FLUSH PRIVILEGES;,否则新权限不生效; - 若目标库版本是 8.0+,注意
mysql.proxies_priv表结构变化,部分旧 dump 可能报错,建议优先用pt-show-grants或纯SHOW GRANTS方式。
最容易被忽略的是:权限语句中的数据库名和表名是否在目标库真实存在。比如 GRANT SELECT ON `reporting`.`daily_summary` TO ...,如果 reporting 库或 daily_summary 表还没导入,这条 GRANT 会报错失败——所以权限迁移一定要放在数据迁移完成之后。

















