查mysql.user表需高权限,普通用户无权访问;Host字段表示授权登录范围而非实时连接来源;account_locked和password_expired才是账号是否可用的关键指标;实时连接应查PROCESSLIST或performance_schema.threads。

查 mysql.user 表前必须确认权限和连接用户
直接 SELECT * FROM mysql.user 会失败,除非你用的是 root 或拥有 SELECT 权限的高权限账号。普通账号即使能连上 MySQL,也大概率看不到 mysql 系统库内容——这不是配置问题,是默认安全策略。
常见错误现象:ERROR 1142 (42000): SELECT command denied to user 'xxx'@'%' for table 'user'
- 先用
SELECT CURRENT_USER();确认当前登录身份 - 再执行
SHOW GRANTS FOR CURRENT_USER();检查是否含ON mysql.*权限 - 如果没权限,别硬试视图或临时表绕过,那是徒劳;得找 DBA 加权限或换账号
统计不同 Host 的活跃用户数时注意通配符含义
mysql.user 表里的 Host 字段不是“当前连接来源”,而是“该账号允许从哪些主机登录”的授权范围。比如 '%'、'localhost'、'192.168.1.%' 都算合法值,但它们不反映实时在线状态。
所以“活跃用户”在这里实际指“已创建且未被 DROP USER 删除的账号”,而非当前 SHOW PROCESSLIST 里正在运行的连接。
- 用
SELECT Host, COUNT(*) FROM mysql.user GROUP BY Host;可快速看分布 -
'%'匹配所有非本地 IP,但不包括localhost(MySQL 认为它是 Unix socket 专用,逻辑上独立) - 如果看到大量重复
Host值,可能是批量创建账号时没清理旧记录,建议结合User和authentication_string是否为空判断是否僵尸账号
mysql.user 中的 account_locked 和 password_expired 才是关键活跃性指标
真正决定一个账号“能不能用”的,不是它在不在表里,而是这两列:
-
account_locked = 'Y':账号被锁死,无论密码对不对都拒绝登录 -
password_expired = 'Y':密码过期,首次登录会被强制重置(取决于default_password_lifetime设置) - 两者只要有一个是
'Y',这个账号就无法正常建立新连接,即使Host和User都合法
实操建议:SELECT User, Host, account_locked, password_expired FROM mysql.user WHERE account_locked = 'Y' OR password_expired = 'Y';
想看“此刻真正连着的用户”得查 information_schema.PROCESSLIST 或 performance_schema.threads
mysql.user 是静态账号定义,而 PROCESSLIST 才反映实时连接。但要注意:普通用户默认查不到其他人的连接,只有 PROCESS 权限才可看全量。
- 执行
SHOW PROCESSLIST;最快,但只显示当前用户自己的连接(除非有权限) - 更全的写法:
SELECT DISTINCT USER, HOST FROM information_schema.PROCESSLIST WHERE USER != ''; - 如果启用了
performance_schema且开启 threads 收集,SELECT USER, HOST FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' AND PROCESSLIST_ID IS NOT NULL;更准,还能过滤后台线程
容易踩的坑:把 mysql.user 的行数当成并发连接数——这两者数量级可能差十倍以上,尤其在连接池复用场景下。










