MySQL 5.7 支持 GRANT 隐式建用户并带 IDENTIFIED BY,8.0 必须分离 CREATE USER 和 GRANT,且需显式指定认证插件(如 caching_sha2_password),否则连接失败或报错 ERROR 1064。

MySQL 5.7 和 8.0 的 GRANT 语法根本差异在哪
核心区别不是“能不能用 GRANT”,而是“GRANT 是否允许隐式建用户 + 是否接受 IDENTIFIED BY 子句”。MySQL 5.7 支持 GRANT ... TO 'u'@'h' IDENTIFIED BY 'p',一条语句完成建用户+赋权;MySQL 8.0.12+ 已废弃该写法,执行直接报 ERROR 1064 (42000)。更隐蔽的问题是:即使你没写 IDENTIFIED BY,若脚本里混用了 CREATE USER 但没指定认证插件(如 caching_sha2_password),老应用连接器(如 PyMySQL
如何写出跨 5.7 / 8.0 都能跑的权限脚本
唯一可靠路径是「显式分离创建与授权」,并控制认证方式。不依赖版本判断逻辑,避免在 CI/CD 中引入条件分支带来的维护成本:
-
CREATE USER IF NOT EXISTS 'u'@'%' IDENTIFIED WITH mysql_native_password BY 'p'—— 显式指定插件,兼容所有客户端 -
GRANT SELECT, INSERT ON db.* TO 'u'@'%'—— 纯权限语句,不含任何认证或密码子句 - 删掉所有
FLUSH PRIVILEGES——CREATE USER和GRANT自带持久化,手动刷反而掩盖连接目标错配问题(比如连到从库执行) - 避免
GRANT ALL PRIVILEGES直接授给生产账号;8.0 下它会隐式包含APPLICATION_PASSWORD_ADMIN等高危权限,超出最小必要原则
SHOW GRANTS 输出格式变化导致的运维工具失效
如果你的权限审计、回滚生成或同步工具靠正则解析 SHOW GRANTS FOR 'u'@'%' 结果,MySQL 8.0 会悄悄破坏逻辑:
- 8.0 不再输出
GRANT USAGE ON *.* TO 'u'@'%'—— 这条隐式存在的基础权限被省略,工具可能误判为“无任何权限” - 角色相关语句(如
WITH ADMIN OPTION)只在 8.0 出现,5.7 解析会失败或跳过 - 推荐改用查询系统表:
SELECT * FROM mysql.role_edges WHERE TO_HOST = '%'(8.0)或SELECT * FROM mysql.user WHERE User = 'u'(通用),绕过文本解析陷阱
CI/CD 流水线中必须检查的三个点
自动化部署最常翻车的地方不在 SQL 本身,而在环境认知偏差:
- 确认目标实例真实版本:不要信配置文件或标签,执行
SELECT VERSION()获取实时值,避免因 Docker 镜像 tag 错误(如mysql:8实际拉取的是 8.0.33,而测试环境是 8.0.39)引发行为差异 - 检查客户端驱动是否支持
caching_sha2_password:PyMySQL ≥ 1.0、MySQL Connector/Python ≥ 8.0.12 才行;否则即使用户创建成功,应用也连不上,报错是Authentication plugin 'caching_sha2_password' cannot be loaded - 权限脚本执行后,必须验证连接有效性:用目标应用的账号和驱动直连一次,执行
SELECT 1,不能只看 SQL 是否“执行成功”
实际兼容性最脆弱的环节,往往不是语法本身,而是权限生效后那层看不见的连接握手——它既依赖服务端插件,也卡在客户端驱动实现上。只要有一端不匹配,GRANT 再成功也是空转。


















