MySQL show processlist 中 Sleep 与 Query 的比例分析

7次阅读

Sleep状态多不等于数据库卡顿,它仅表示连接空闲等待命令;真正需警惕的是长时间未释放的事务或未加索引的慢查询。

MySQL show processlist 中 Sleep 与 Query 的比例分析

为什么 show processlist 里大量 Sleep 状态不等于数据库卡了

mysqlSleep 状态表示连接已建立但当前没有执行任何 SQL,它只是空闲等待新命令——这本身是正常现象,尤其在使用连接池(如 HikariCP、Druid)的 java 应用中。Sleep 连接是否危险,取决于它的持续时间、数量与业务负载的关系。如果 Sleep 连接平均存活数小时且长期不释放,才可能指向连接未正确 close、连接池配置不合理或应用存在连接泄漏。

如何快速判断 Sleep 连接是否异常

直接查 SHOW PROCEsslIST 不够,需结合 Time 列和连接来源分析:

  • Time 值大于应用层连接超时(如 Druid 的 maxWait 或 MySQL 的 wait_timeout)仍不退出 → 检查应用是否忘记 connection.close() 或连接池未启用 testOnBorrow/testWhileIdle
  • 大量 Sleep 来自同一 IP + 同一用户 + 相同程序名(Info 为空)→ 很可能是连接池预热后未被复用,或连接池最小空闲数(minIdle)设得过高
  • Sleep 连接数持续 > 连接池最大值(maxActive / maximumPoolSize)→ 存在连接未归还,需抓取应用日志中的 JDBC 调用

Query 状态长时间不结束才是真问题

Query 状态代表线程正在执行 SQL,此时关注点完全不同:

  • State 显示 Sending dataCopying to tmp table 时间过长 → 检查是否缺少索引、是否扫描全表、是否排序/分组数据量过大
  • State 卡在 LockedWaiting for table metadata lock → 表结构变更(ALTER TABLE)阻塞了查询,或长事务未提交导致 MDL 锁未释放
  • Info 字段显示的是 select ... FOR UPDATETime 持续增长 → 检查事务是否遗漏 COMMIT 或存在跨服务未同步的分布式事务

用 SELECT FROM information_schema.PROCESSLIST 做量化分析

人工看 SHOW PROCESSLIST 容易漏判,建议用 SQL 统计比例:

SELECT   COUNT(*) AS total,   SUM(IF(COMMAND = 'Sleep', 1, 0)) AS sleep_cnt,   SUM(IF(COMMAND = 'Query', 1, 0)) AS query_cnt,   ROUND(100 * SUM(IF(COMMAND = 'Sleep', 1, 0)) / COUNT(*), 2) AS sleep_pct FROM information_schema.PROCESSLIST;

再叠加过滤条件定位风险连接:

SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO FROM information_schema.PROCESSLIST WHERE COMMAND = 'Sleep' AND TIME > 600; -- 空闲超10分钟的连接

注意:information_schema.PROCESSLIST 中的 TIME 是该线程空闲/执行的秒数,不是系统时间戳;且该视图只反映查询发起时刻的快照,高并发下需多次采样比对。

真正要警惕的不是 Sleep 多,而是 Sleep 连接里混着长时间未释放的事务(trx_state = 'ACTIVE'),或者 Query 状态里藏着没加索引的慢查询 —— 这些才是拖垮性能的根因。

text=ZqhQzanResources