先执行select user(), current_user()确认实际认证账号,再用show grants for current_user()查真实权限;两者不一致说明mysql按host匹配选中了权限更小的同名用户,show grants仅反映current_user()对应记录的权限。

先执行 SELECT USER(), CURRENT_USER(); —— 90% 的“权限不足”根本不是没授权,而是你连的根本不是你以为的那个用户。
查清实际认证账号和真实生效权限
MySQL 权限校验只认 CURRENT_USER() 返回的账号,不是你登录时写的那个。比如 USER() 是 'app'@'192.168.1.100',而 CURRENT_USER() 是 'app'@'%',那就要立刻查后者有没有被授过权。
- 运行
SHOW GRANTS FOR CURRENT_USER();—— 这是唯一反映当前会话真实权限的命令;别用SHOW GRANTS FOR 'app'@'192.168.1.100',它可能根本不存在或不生效 - 如果输出只有
GRANT USAGE ON *.* TO ...,说明这个账号只允许登录,不能操作任何对象 - 跨库查询(如视图里查
otherdb.table)必须显式授权:仅GRANT SELECT ON mydb.*不够,得补GRANT SELECT ON otherdb.table TO ... - MySQL 8.0 启用角色后,
CURRENT_USER()可能有角色但没激活:检查是否执行了SET ROLE role_name;,或配置了activate_all_roles_on_login=ON
确认报错对应的具体「命令+对象」权限缺口
错误信息里藏着关键线索,比如 ERROR 1142 (42000): SELECT command denied to user 'u'@'localhost' for table 'mysql.user',说明缺的是对 mysql.user 表的 SELECT 权限,不是整个 mysql 库。
- 用
SHOW GRANTS FOR CURRENT_USER() ON mysql.user;(MySQL 8.0.16+ 支持)直接验证该表权限,旧版本跳过即可 - 视图加载失败常见于
ERROR 1449(DEFINER 账号不存在)或ERROR 1142(DEFINER 有账号但缺基表权限),此时要查SHOW CREATE VIEW view_name\G看DEFINER和SQL SECURITY - 嵌套视图还额外需要
SHOW VIEW权限,否则报ERROR 1349,跟语法无关 - 执行
mysqldump失败,除了SELECT,还必须有SHOW VIEW、TRIGGER、LOCK TABLES
检查 host 匹配、连接复用与权限刷新时机
权限写了,FLUSH PRIVILEGES; 也执行了,还是报错?大概率卡在连接层。
-
'u'@'localhost'和'u'@'127.0.0.1'是两个不同账号;Linux 下localhost走 socket,127.0.0.1走 TCP,应用连哪个,就得给哪个授权 - 长连接池(如 HikariCP)或 PHP 的旧扩展不会自动重载权限,必须断开重连才能生效
-
FLUSH PRIVILEGES;在用GRANT授权后通常自动触发,但直接改mysql.user表后必须手动执行;不过——千万别直接改系统表,风险高且不可靠 - 存在匿名用户
''@'localhost'时,它会优先匹配无用户名的连接,导致权限意外降级:用DROP USER ''@'localhost';清理
最易被忽略的点:CURRENT_USER() 返回的账号,其 plugin 字段是否兼容客户端?MySQL 8.0 默认用 caching_sha2_password,老客户端连不上会报 ERROR 1045,看起来像权限问题,其实是认证失败。











