升级前必须导出旧版本的权限数据
MySQL 5.7 及更早版本的权限存储在
mysql库的
user、
db、
tables_priv等表中,而 8.0+ 改用角色模型和更严格的账户结构(如
authentication_string字段替代
password)。直接复制
mysql库会导致新版本启动失败或权限失效。
正确做法是用
mysqldump导出逻辑权限语句:
mysqldump --no-create-info --skip-extended-insert -u root -p mysql user db tables_priv columns_priv procs_priv proxies_priv > mysql_grants.sql
--no-create-info:避免导出建表语句,只取数据
--skip-extended-insert:每行一个
INSERT,便于后续 grep 或 sed 过滤 务必排除
columns_priv和
procs_priv中含特殊字符(如换行、引号)的记录,否则导入会报错
ERROR 1064
升级后不能直接导入 dump 文件
MySQL 8.0 的
mysql.user表字段大幅变更(例如移除了
Password列,新增
account_locked、
password_reuse_history),且默认认证插件从
mysql_native_password变为
caching_sha2_password。直接执行旧 dump 里的
INSERT INTO mysql.user ...会触发字段不匹配或认证插件不兼容错误。
应改用
SHOW GRANTS方式重建权限: 对每个用户执行:
SHOW GRANTS FOR 'username'@'host';将输出保存为
grants_user.sql,手动替换
IDENTIFIED BY为
IDENTIFIED WITH mysql_native_password BY(如需兼容老客户端) 导入时先创建用户:
CREATE USER 'username'@'host' IDENTIFIED WITH mysql_native_password BY 'pwd';,再执行
GRANT ...
跨大版本迁移必须重置 root 密码并校验 plugin
MySQL 8.0 启动后,
root@localhost默认使用
caching_sha2_password,但旧备份中的密码哈希值无法被新插件识别,导致连不上库。这不是权限丢失,而是认证失败。 启动时加
--skip-grant-tables,然后执行:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'newpass';检查是否生效:
SELECT host,user,plugin FROM mysql.user WHERE user='root';,确保
plugin是
mysql_native_password或目标插件 若应用连接报
Client does not support authentication protocol,说明驱动太老(如 MySQL Connector/J
自动化迁移脚本要避开 system user 和 expired 账户
MySQL 8.0 内置了
mysql.infoschema、
mysql.sys等系统账户,其
plugin为
auth_socket或
sha256_password,且密码为空或不可逆。批量迁移时若未过滤,脚本会尝试重置这些账户,引发服务异常。
安全过滤条件示例(在生成
SHOW GRANTS命令前):
SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';')
FROM mysql.user
WHERE account_locked='N'
AND password_expired='N'
AND user NOT IN ('mysql.infoschema','mysql.session','mysql.sys');另外,
GRANT OPTION权限在 8.0 中受
role_admin权限约束,单纯导入
GRANT ... WITH GRANT OPTION不足以让普通用户授予他人权限,必须额外赋权:
GRANT ROLE_ADMIN ON *.* TO 'admin'@'%';
真正麻烦的是存储过程和函数里的 DEFINER,升级后若原定义者不存在,调用会报
ERROR 1449—— 这类对象得逐个用
ALTER DEFINER修正,没法靠脚本全自动兜底。
