mysql版本升级时如何避免权限丢失_mysql权限迁移方案

来源:这里教程网 时间:2026-02-28 20:49:28 作者:

升级前必须导出旧版本的权限数据

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
修正,没法靠脚本全自动兜底。

相关推荐