SHOW GRANTS输出不可直接重放,因其不含FLUSH PRIVILEGES、不处理USAGE权限及角色代理关系,且MySQL 8.0下含认证哈希的语句会触发ERROR 1064;须通过查询mysql.user等系统表拼接CREATE USER+GRANT+SET DEFAULT ROLE+FLUSH PRIVILEGES组合脚本方可可靠迁移。

SHOW GRANTS 输出不是可执行 SQL,直接重定向会失效
SHOW GRANTS FOR 'user'@'host' 返回的是带引号的、带 GRANT 关键字的语句,但**不包含 FLUSH PRIVILEGES,也不处理权限通配符(如 USAGE)或角色继承关系**。更关键的是:MySQL 8.0 默认开启 sql_mode=STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,而部分导出语句(如空密码、无认证插件声明)在重放时会报错。
常见错误现象:ERROR 1064 (42000): You have an error in your SQL syntax,多因导出内容含 IDENTIFIED WITH caching_sha2_password AS '$A$...' 这类哈希值,直接执行会触发语法错误。
- 必须用
SELECT从mysql.role_edges、mysql.proxies_priv等系统表补全角色与代理权限 - 密码字段不能直接拼进
CREATE USER,应拆成独立ALTER USER ... IDENTIFIED WITH ... BY 'xxx' -
SHOW GRANTS不返回SET DEFAULT ROLE,需单独查mysql.default_roles
用 SELECT 拼接 CREATE USER + GRANT 组合语句才可靠
绕过 SHOW GRANTS 的局限,直接查元数据表生成可执行脚本。核心思路是分三步构造:
- 第一步:生成
CREATE USER(含IDENTIFIED WITH和REQUIRE子句) - 第二步:生成各 schema/table 级
GRANT(过滤掉USAGE权限) - 第三步:生成
GRANT ROLE和SET DEFAULT ROLE
示例(单用户):
SELECT CONCAT('CREATE USER ', QUOTE(user), '@', QUOTE(host),
' IDENTIFIED WITH ', plugin,
CASE WHEN authentication_string != '' THEN CONCAT(' AS ', QUOTE(authentication_string)) ELSE '' END,
' REQUIRE ', ssl_type,
' PASSWORD EXPIRE ', password_expired,
' ACCOUNT ', account_locked,
';') AS stmt
FROM mysql.user
WHERE user = 'myuser' AND host = 'localhost';
注意:ssl_type 字段值可能是 NONE、SSL、X509 或具体 cipher,需映射为合法 REQUIRE 子句;account_locked 是 ENUM,值为 Y/N,要转成 LOCKED/UNLOCKED。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
mysqldump --no-data --skip-triggers 对权限导出无效
mysqldump -u root -p --no-data --skip-triggers mysql 确实能导出 user、db 等表结构,但**MySQL 8.0 已废弃 mysql.db 表的权限存储方式,改用 mysql.tables_priv、mysql.columns_priv 等更细粒度表,且所有权限字段都是 SET 类型(如 Select_priv),无法直接映射为标准 GRANT SELECT 语法**。
更麻烦的是:mysqldump 导出的 INSERT 语句写入 mysql.* 表本身是被禁止的(除非禁用 secure_file_priv 并用 --skip-extended-insert 手动改写),且跳过 FLUSH PRIVILEGES 将导致权限不生效。
- 不要依赖
mysqldump做权限迁移 - 不要手动 INSERT 到
mysql.*表 —— MySQL 8.0 会静默忽略或报错 - 必须通过
GRANT/CREATE USER等 DCL 语句重建
导出脚本里必须显式处理 FLUSH PRIVILEGES 和角色激活
即使所有 GRANT 语句执行成功,权限也不会立刻生效——MySQL 8.0 的缓存机制要求显式刷新。而角色默认不激活,需额外命令。
- 每个用户脚本末尾必须加:
FLUSH PRIVILEGES; - 若用户有默认角色,必须加:
SET DEFAULT ROLE ALL TO 'user'@'host'; - 若脚本用于跨实例恢复,还要检查目标实例是否启用对应认证插件(如
caching_sha2_password),否则CREATE USER会失败
容易被忽略的一点:SHOW GRANTS 输出里如果出现 GRANT PROXY ON ''@'' TO 'u'@'h',说明存在代理权限,这需要单独查 mysql.proxies_priv 表生成 GRANT PROXY 语句,且必须放在 FLUSH PRIVILEGES 之前。

















