MySQL权限不生效的根本原因是CURRENT_USER()与USER()不一致,说明认证账号匹配失败;必须依据CURRENT_USER()返回的'user'@'host'精确授权并重连,旧会话权限不会更新。

根本不是权限没给够,而是 MySQL 根本没认出你是谁——'user'@'host' 这个组合不匹配,权限就白给了。
SELECT USER() 和 CURRENT_USER() 输出不一样?那就别急着建库
这是最常被忽略的起点。MySQL 认用户,只看 CURRENT_USER() 返回的值,而不是你自以为登录用的账号。
-
SELECT USER()显示你「声称」自己是谁(比如'admin'@'192.168.1.100') -
SELECT CURRENT_USER()显示 MySQL「实际匹配」到哪个账户(很可能是'admin'@'%'或'admin'@'192.168.1.%') - 如果两者不同,说明你连接时用的 host 没被 GRANT 语句覆盖——比如你 GRANT 了
'admin'@'localhost',但实际连的是'admin'@'127.0.0.1',这俩在 MySQL 里是两个账户
GRANT ALL PRIVILEGES ON *.* 生效的前提是 host 完全一致
MySQL 不做模糊匹配,'user'@'192.168.1.%' 不等于 'user'@'192.168.1.100',也不等于 'user'@'%'。
- 执行
SHOW GRANTS FOR 'user'@'host'时,host必须和CURRENT_USER()输出一模一样,否则看到的可能是空或只有USAGE - 如果连接来源是动态 IP 或容器网络,建议用
'user'@'192.168.1.%'而非'user'@'%'(后者有安全风险) -
GRANT ALL PRIVILEGES ON *.* TO 'user'@'localhost'对通过 TCP 连接(哪怕连本地 127.0.0.1)完全无效——因为 MySQL 把localhost当作 socket 连接专用
FLUSH PRIVILEGES 没执行,或者执行了但没权限执行
权限变更写入 mysql.user 表后,必须刷新才能生效;但这个操作本身需要 RELOAD 权限。
- 普通用户即使被
GRANT ALL PRIVILEGES ON *.*,也默认没有RELOAD权限(MySQL 8.0+ 更严格) - 所以
FLUSH PRIVILEGES得由 root 或带RELOAD的管理员执行,否则你授完权就走人,权限其实还在内存里没加载 - 验证方式:改完权限后,断开重连,再跑一次
SELECT CURRENT_USER(); SHOW GRANTS;看是否更新
CREATE DATABASE 报 ERROR 1044 却显示有 ALL?可能卡在角色或 sql_mode 上
MySQL 5.7+ 的角色机制和 8.0+ 的默认 sql_mode 是两个安静的“拦路虎”。
- 如果你的用户被赋予的是角色(如
GRANT dba_role TO 'user'@'host'),但没执行SET DEFAULT ROLE dba_role TO 'user'@'host',那SHOW GRANTS会显示角色名,实际权限不激活 - MySQL 8.0 默认启用
sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,某些非法字符集/校对规则(如utf8mb4_0900_a拼错)会导致CREATE DATABASE直接拒绝,错误码仍是 1044,容易误判为权限问题 - 检查命令:
SELECT @@sql_mode;、SELECT * FROM mysql.role_edges WHERE FROM_HOST = '%';
真正卡住的地方,往往不在 SQL 语句本身,而在你没意识到 MySQL 正在用哪个 'user'@'host' 身份运行这条语句——所有权限、角色、甚至连接协议(socket vs TCP),都从这里开始分支。漏掉一次 CURRENT_USER() 核对,后面每步都在给错误对象授权。


















