SELECT USER()和CURRENT_USER()可确认真实登录身份,前者显示客户端声明的用户@主机,后者显示权限系统认证的账号;若不一致需检查mysql.user表Host字段匹配;SHOW GRANTS FOR CURRENT_USER()查看实际生效权限;具体操作报错信息(如ERROR 1142)才是权限验证的最终依据。

用 SELECT USER(), CURRENT_USER() 确认当前连接身份
很多人以为 mysql -u alice 就一定以 alice 身份运行,其实未必——比如没加 -p 时可能被匿名用户匹配,或 host 匹配规则导致实际登录的是 'alice'@'%' 而非 'alice'@'localhost'。
执行这两条语句能立刻看清真实上下文:
SELECT USER(); -- 显示客户端声明的用户名@主机(可能带引号)<br>CURRENT_USER(); -- 显示 MySQL 实际认证通过的账号(权限系统查表所得)如果两者不一致,说明权限没按预期加载,得回头检查
mysql.user 表里的 Host 字段是否精确匹配。
用 SHOW GRANTS FOR CURRENT_USER() 查看生效权限
SHOW GRANTS 不等于“你写了什么”,而是“此刻真正起效的权限组合”。常见误区是只查 SHOW GRANTS FOR 'alice'@'localhost',但实际连接可能是 'alice'@'%',结果看到的权限列表完全不对。
必须用 CURRENT_USER() 动态查,才能反映真实授权状态:
SHOW GRANTS FOR CURRENT_USER();注意输出里每条
GRANT 后面是否带 WITH GRANT OPTION;没有的话,即使有 SELECT 权限也无法转授他人。另外,如果看到 USAGE 单独一行,基本等于“啥权限都没有”,只是允许连接而已。
用具体操作反向验证权限(比如 SELECT / INSERT 报错)
光看 SHOW GRANTS 不够,有些权限(如列级权限、存储过程执行权)不会在全局 GRANT 里显式列出,得靠实际操作触发判断。
典型验证路径:
- 尝试
SELECT * FROM mysql.user;—— 如果报ERROR 1142 (42000): SELECT command denied to user,说明连系统库都没读权限 - 对目标业务表执行
INSERT INTO orders VALUES (...);—— 报ERROR 1142且明确提到表名,说明INSERT权限缺失或作用域不对(比如只给了db1.*却去写db2.orders) - 执行
CREATE TABLE test(a INT);—— 报ERROR 1044 (42000): Access denied for user ... to database 'test',说明缺少CREATE权限或数据库不存在且无CREATE DATABASE
SELECT / INSERT / EXECUTE)必须和你预期的完全对应,否则就是权限没落到正确对象上。权限变更后必须执行 FLUSH PRIVILEGES 吗?
直接改 mysql.user 表后,必须执行 FLUSH PRIVILEGES; 才能让内存缓存更新;但用 GRANT / REVOKE 命令修改则不需要——MySQL 会自动重载。
所以线上排查时,先确认权限是怎么加的:
- 如果是
GRANT SELECT ON mydb.* TO 'bob'@'10.0.0.%';→ 不用 flush,立即生效 - 如果是
UPDATE mysql.user SET Select_priv='Y' WHERE User='bob';→ 必须FLUSH PRIVILEGES;,否则永远不生效 - 如果改完没 flush 又连不上,别急着删账号,先用
mysqld_safe --skip-grant-tables启动绕过权限检查再修
SELECT 看到权限字段已改,但新连接还是拒绝访问,八成是漏了 FLUSH。权限验证不是一次性动作,特别是涉及 host 匹配、列权限、角色继承时,CURRENT_USER() 和具体操作报错信息才是最可靠的依据。别信配置,要信执行结果。


















