用户无SELECT权限因未显式授权mysql.user表,需用root执行GRANT SELECT ON mysql.user TO 'xxx'@'localhost';并FLUSH PRIVILEGES;注意localhost与127.0.0.1视为不同账号,且必须USE mysql;后查询。

直接看用户有没有 SELECT 权限
报错 SELECT command denied to user 'xxx'@'localhost' for table 'user',第一反应不是改表或重启,而是确认这个用户在 mysql 库上压根没被授予 SELECT 权限。因为 user 表属于系统库 mysql,普通账号默认禁止访问它——哪怕你是用 root 创建的子账号,也不自动继承查 user 表的权限。
- 用 root 登录后,先执行:
SHOW GRANTS FOR 'xxx'@'localhost';(把xxx换成实际用户名) - 如果输出里只有
USAGE ON *.*或者只写了SELECT ON `myapp`.*这类非系统库的授权,那就确认没权限 - 特别注意:
GRANT SELECT ON *.*也不包含mysql库,MySQL 明确将系统库排除在通配符之外
给用户加 mysql.user 表的 SELECT 权限
不能笼统授 SELECT ON mysql.*,MySQL 8.0+ 默认禁止对整个 mysql 库授权;必须精确到表。最常用且安全的做法是只开 user 表的读权限:
- 执行:
GRANT SELECT ON mysql.user TO 'xxx'@'localhost'; - 如果还要查
db、tables_priv等其他权限表,得一条条加,例如:GRANT SELECT ON mysql.db TO 'xxx'@'localhost'; -
FLUSH PRIVILEGES;必须执行,否则权限不生效(尤其 Windows 下容易漏这步) - 授权后不用重启 MySQL 服务,但客户端要断开重连才能识别新权限
为什么用 localhost 却查不到,换 127.0.0.1 就报错?
MySQL 把 'xxx'@'localhost' 和 'xxx'@'127.0.0.1' 当作两个完全不同的账号,权限互不影响。常见踩坑点:
- Navicat 或程序连接字符串里填的是
127.0.0.1,但你只给localhost授权了 → 查不到 - 检查账号存在性:
SELECT User, Host FROM mysql.user WHERE User = 'xxx';,看返回的Host列到底是哪个值 - 若需兼容两者,可分别授权:
GRANT SELECT ON mysql.user TO 'xxx'@'localhost';和GRANT SELECT ON mysql.user TO 'xxx'@'127.0.0.1'; - 不建议直接用
'%',尤其是查mysql.user这种敏感表,安全风险高
查 user 表却提示表不存在?注意 database 名大小写和默认库
报错有时看着像权限问题,其实是根本没进对库。比如执行 SELECT * FROM user; 时,如果当前没 USE mysql;,MySQL 会去当前默认库找 user 表,而默认库几乎不可能叫 mysql。
- 先确认当前库:
SELECT DATABASE();,大概率返回NULL或某个业务库名 - 必须显式切换:
USE mysql;,再执行SELECT * FROM user; - Linux 下表名严格区分大小写,Windows/macOS 默认不区分,但写法统一推荐小写加反引号:
SELECT * FROM `user`; - 如果仍提示
Unknown table 'user',说明你连的不是本地 MySQL 实例,而是 RDS 或其他托管服务(如阿里云 RDS 默认屏蔽mysql库访问)
真正麻烦的不是授权动作本身,而是权限对象(库/表/主机)三者必须严丝合缝匹配;少一个字符、多一个空格、大小写不一致,都会让 GRANT 形同虚设。


















