user()返回客户端声明的用户名和主机,current_user()返回mysql认证通过的账号;二者需并排对比,调试权限时应重点关注后者。

怎么用 USER() 和 CURRENT_USER() 查当前用户
这两个函数看着像,但返回的不是一回事:USER() 返回客户端声明的用户名和主机(比如 'admin@192.168.1.100'),是连接时填的;CURRENT_USER() 返回 MySQL 实际认证通过的账号(比如 'admin@%'),受权限表匹配规则影响。多数时候你真正该看的是后者,尤其在调试权限问题时。
- 直接执行
SELECT USER(), CURRENT_USER();就能并排对比 - 如果用代理或中间件(如 ProxySQL、MaxScale),
USER()可能显示代理 IP,而CURRENT_USER()才反映后端真实认证账号 - 注意:二者都只对当前会话有效,不能跨连接查别人
查所有活跃会话用 SHOW PROCESSLIST 或 information_schema.PROCESSLIST
SHOW PROCESSLIST 是最常用的实时会话快照命令,但默认只显示当前用户的会话;要查全部,必须有 PROCESS 权限(通常只有管理员有)。
- 执行
SHOW FULL PROCESSLIST;可看到完整 SQL(避免被截断) - 等价的查询方式:
SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO FROM information_schema.PROCESSLIST; - 常见陷阱:普通用户执行
SHOW PROCESSLIST时,USER列显示的是该会话的CURRENT_USER(),不是USER()—— 这点文档没明说,但实测如此 - MySQL 8.0+ 中,
performance_schema.threads更详细,但默认不开启线程事件收集,且字段命名和PROCESSLIST不一致(比如用PROCESSLIST_USER而非USER)
HOST 字段为什么经常是 % 或 localhost,但实际连的是 IP?
这是权限系统匹配逻辑导致的错觉。HOST 在 mysql.user 表里定义的是“允许从哪来”,不是“当前从哪来”。比如你用 mysql -h 127.0.0.1 -u admin 连,CURRENT_USER() 可能仍是 'admin@%',因为 'admin'@'127.0.0.1' 不存在,而 'admin'@'%' 匹配成功。
- 检查具体账号定义:执行
SELECT User, Host FROM mysql.user WHERE User = 'admin'; - 注意 Unix socket 连接会被识别为
localhost,哪怕你指定了-h 127.0.0.1;想强制走 TCP,得加--protocol=tcp -
HOST值带通配符(如'%.example.com')时,DNS 解析失败会导致匹配降级到'%',这时看到的HOST是'%',但实际来源可能是未解析的 IP
会话信息里 COMMAND 为 Sleep 却占着连接,怎么判断是不是泄漏?
Sleep 状态本身不危险,危险的是长期不活动还卡着连接数上限。关键要看 TIME(秒数)和应用行为是否匹配。
- 确认是否启用了连接池:比如 Java 的 HikariCP 默认
connection-timeout=30000,空闲连接会在 30 秒后回收,此时你看到的Sleep时间不会超过这个值 - MySQL 侧超时控制靠两个参数:
wait_timeout(交互式连接)和interactive_timeout(非交互式),默认 28800 秒(8 小时),远大于常见业务需求 - 如果发现大量
Sleep连接TIME > 300且INFO为空,大概率是应用没正确 close() 或连接池配置不合理 - 临时排查可加条件过滤:
SELECT * FROM information_schema.PROCESSLIST WHERE COMMAND = 'Sleep' AND TIME > 600;
查会话不是单纯看“谁在线”,而是要结合 CURRENT_USER() 理解权限上下文,用 PROCESSLIST 对齐应用行为,再盯住 TIME 和 COMMAND 判断资源是否滞留——这些点串起来,才算是把连接状态看明白了。











