MySQL 5.7 升级至 8.0 后权限系统重构:user@host 严格精确匹配、caching_sha2_password 认证插件导致兼容性问题、系统表只读且 GRANT/REVOKE 为唯一途径、角色与动态权限引入、密码过期与账户锁定成默认可配项。

MySQL 5.7 升级到 8.0 后,用户权限系统不是“小修小补”,而是底层逻辑重构——最直接的表现是:你以前能连上的账号,升级后大概率报 Access denied for user 'ODBC'@'localhost';你用 GRANT 赋的权限,可能在新版本里查不到或不生效。
user@host 是严格字面匹配,不是通配符模糊匹配
MySQL 8.0 的权限判定完全基于 user@host 组合的**精确字符串匹配**,不再有隐式归并或宽松解析。
-
'admin'@'localhost'和'admin'@'127.0.0.1'是两个独立用户,哪怕密码一样、权限一样,也不能互相替代 - ODBC、Navicat、Java JDBC 等客户端默认连接行为不同:有些强制走 TCP(即用
127.0.0.1),有些优先走 socket(即localhost),结果可能命中完全不同的账户 - 执行
SELECT User, Host FROM mysql.user;会看到大量重复用户名但 Host 不同的记录,别删——它们各自负责不同连接路径
caching_sha2_password 认证插件导致连接失败或首次延迟
8.0 默认为所有新用户启用 caching_sha2_password,它比 mysql_native_password 更安全,但也更“挑客户端”。
- 老版本驱动(如
mysql-connector-java < 8.0.16、PHPmysqlnd < 5.0.12)无法加载该插件,报错:Authentication plugin 'caching_sha2_password' cannot be loaded - 即使驱动支持,首次 TCP 连接(尤其是 root 或长密码用户)会卡 1–3 秒——这是 RSA 公钥协商 + 加密运算的固有开销,不是配置错误
- 临时兼容方案是显式降级插件:
ALTER USER 'your_user'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';,但仅限过渡,8.4 已彻底废弃该插件
系统权限表不可直写,GRANT/REVOKE 成唯一合法途径
MySQL 8.0 彻底移除了 MyISAM 系统表,mysql.user 等变成只读视图,任何 INSERT INTO mysql.user 或 UPDATE mysql.db 都会失败。
- 直接修改系统表的运维脚本、旧版备份恢复工具(尤其含
--all-databases的 mysqldump)若混入了mysql库,会导致权限元数据损坏 -
CREATE USER和GRANT语句现在是原子操作,且必须指定@host,省略@'%'会被自动补为@'localhost',容易误判范围 - 角色(
ROLE)成为权限管理新范式,但 5.7 没有角色概念,迁移时需手动将角色权限拆解为用户级GRANT
权限继承与动态权限机制改变默认行为
8.0 引入动态权限(如 BACKUP_ADMIN、CLONE_ADMIN)和更细粒度的权限作用域,但默认不向后兼容旧习惯。
- 某些旧权限(如
FILE、SHUTDOWN)不再隐式包含子权限,需显式授予;而新增的SYSTEM_VARIABLES_ADMIN等权限不会被GRANT ALL自动覆盖 - 使用
SHOW GRANTS FOR 'user'@'host'查看权限时,输出格式更结构化,但不会显示通过角色间接获得的权限——得额外查mysql.role_edges - 密码过期策略(
PASSWORD EXPIRE)和账户锁定(ACCOUNT LOCK)成为默认可配项,升级后未重置的老账号可能被静默锁定
真正麻烦的不是某条命令报错,而是权限问题往往藏在连接建立之后:查询能跑、写入被拒、备份失败、监控告警失灵……这些都可能源于 host 匹配偏差或认证插件不匹配。建议升级前先用 mysql --protocol=TCP -h 127.0.0.1 -u ... 和 mysql -S /tmp/mysql.sock -u ... 分别测试同一账号,确认双路径可用性。


















