怎样排查MySQL用户权限不足错误

作者:袖梨 2026-08-31

先执行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'@'%',那就要立刻查后者有没有被授过权。

  1. 运行 SHOW GRANTS FOR CURRENT_USER(); —— 这是唯一反映当前会话真实权限的命令;别用 SHOW GRANTS FOR 'app'@'192.168.1.100',它可能根本不存在或不生效
  2. 如果输出只有 GRANT USAGE ON *.* TO ...,说明这个账号只允许登录,不能操作任何对象
  3. 跨库查询(如视图里查 otherdb.table)必须显式授权:仅 GRANT SELECT ON mydb.* 不够,得补 GRANT SELECT ON otherdb.table TO ...
  4. 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 库。

  1. SHOW GRANTS FOR CURRENT_USER() ON mysql.user;(MySQL 8.0.16+ 支持)直接验证该表权限,旧版本跳过即可
  2. 视图加载失败常见于 ERROR 1449(DEFINER 账号不存在)或 ERROR 1142(DEFINER 有账号但缺基表权限),此时要查 SHOW CREATE VIEW view_nameGDEFINERSQL SECURITY
  3. 嵌套视图还额外需要 SHOW VIEW 权限,否则报 ERROR 1349,跟语法无关
  4. 执行 mysqldump 失败,除了 SELECT,还必须有 SHOW VIEWTRIGGERLOCK TABLES

检查 host 匹配、连接复用与权限刷新时机

权限写了,FLUSH PRIVILEGES; 也执行了,还是报错?大概率卡在连接层。

  1. 'u'@'localhost''u'@'127.0.0.1' 是两个不同账号;Linux 下 localhost 走 socket,127.0.0.1 走 TCP,应用连哪个,就得给哪个授权
  2. 长连接池(如 HikariCP)或 PHP 的旧扩展不会自动重载权限,必须断开重连才能生效
  3. FLUSH PRIVILEGES; 在用 GRANT 授权后通常自动触发,但直接改 mysql.user 表后必须手动执行;不过——千万别直接改系统表,风险高且不可靠
  4. 存在匿名用户 ''@'localhost' 时,它会优先匹配无用户名的连接,导致权限意外降级:用 DROP USER ''@'localhost'; 清理

最易被忽略的点:CURRENT_USER() 返回的账号,其 plugin 字段是否兼容客户端?MySQL 8.0 默认用 caching_sha2_password,老客户端连不上会报 ERROR 1045,看起来像权限问题,其实是认证失败。

相关文章

精彩推荐