最稳妥的用户权限复制方式是导出并重放授权语句,因mysql无内置克隆权限命令;需用show grants获取原用户语句,替换用户名后执行,或使用mysqlpump --users --no-data导出再修改导入。

直接复制用户权限的可靠方式是导出并重放授权语句
MySQL 没有内置的 CLONE USER 或类似命令(8.0.26+ 的 CREATE USER ... FROM 仅复制身份认证信息,不复制权限),所以最稳妥的做法是查出原用户的全部 GRANT 语句,替换用户名后执行。别依赖 SHOW GRANTS FOR 'olduser'@'host' 直接改写——它返回的是带引号的字符串,不能直接执行。
实操建议:
- 用
SELECT CONCAT('GRANT ', privilege, ' ON ', table_schema, '.', table_name, ' TO ''newuser''@''newhost'';') FROM information_schema.role_table_grants WHERE grantee = '''olduser''@''oldhost'''这类查询太局限,漏掉全局/数据库级权限,也难覆盖角色继承 - 正确做法:运行
SHOW GRANTS FOR 'olduser'@'oldhost',把输出结果里的每条GRANT中的'olduser'@'oldhost'手动或脚本替换成'newuser'@'newhost',再逐条执行 - 注意:如果原用户有
WITH GRANT OPTION,新用户也会获得该能力,需确认是否符合安全要求
用 mysqlpump 导出权限时必须加 --users 和 --no-data
想批量迁移多个用户或避免手动拼接,mysqlpump 是更可靠的工具,但它默认不导出用户和权限——很多人卡在这一步。
关键参数组合:
- 必须加
--users,否则只导出数据库对象 - 必须加
--no-data,否则会混入大量表数据,导入失败或污染目标库 - 加上
--skip-triggers --skip-routines --skip-events可进一步精简,聚焦权限本身 - 导出后检查 SQL 文件,确认里面包含
CREATE USER和GRANT语句,且目标用户名已按需修改
CREATE USER ... FROM 在 MySQL 8.0.26+ 中只复制认证属性
看到文档里说 CREATE USER 'newuser'@'host' FROM 'olduser'@'host',别误以为它能复制权限。它只复制 IDENTIFIED WITH ... AS、密码哈希、SSL 设置等认证相关字段,GRANT 一条都不会带过来。
典型误用场景:
- 执行
CREATE USER 'alice'@'%' FROM 'bob'@'%'后,SHOW GRANTS FOR 'alice'@'%'返回空结果 - 若原用户属于某个角色(如
app_reader),新用户也不会自动被SET DEFAULT ROLE或加入该角色 - 这个语法真正价值在于快速复用相同认证策略(比如统一用 caching_sha2_password + 相同密码哈希),而非权限继承
权限克隆后务必验证实际生效范围
即使 SHOW GRANTS 显示一致,也不代表新用户真能访问——常见断点在 host 匹配、SQL_MODE 差异、或被更细粒度的权限覆盖。
验证要点:
- 用新用户连接后执行
SELECT CURRENT_USER(), USER(),确认解析的 host 是否与GRANT中声明的一致(比如'user'@'192.168.1.%'不匹配'user'@'192.168.1.100') - 对关键表执行
SELECT、INSERT等操作,而不是只查information_schema - 如果原用户权限来自角色,记得给新用户显式执行
GRANT role_name TO 'newuser'@'host'并SET DEFAULT ROLE
权限不是“复制即生效”,host 字符串匹配、角色激活、甚至 MySQL 配置中的 sql_mode 都可能让看似相同的 GRANT 行为不同。动手前先看清楚原用户的 CURRENT_USER() 输出,比什么都管用。











