应查 sys.memory_by_thread_by_current_bytes 视图,因其聚合 performance_schema.memory_summary_by_thread_by_event_name 并封装单位换算,而 show processlist 和 performance_schema.threads 不含内存数据。

直接查 sys.memory_by_thread_by_current_bytes,按 current_allocated 降序取前几条,就能看到当前内存占用最高的活跃线程。
为什么不是 SHOW PROCESSLIST 或 performance_schema.threads?
SHOW PROCESSLIST 只显示线程状态和 SQL 文本,不带内存数据;performance_schema.threads 有 thread_id 和 processlist_id,但本身不存内存分配量。真正记录每个线程实时内存消耗的,是 sys.memory_by_thread_by_current_bytes —— 它底层聚合了 performance_schema.memory_summary_by_thread_by_event_name,已做单位换算和可读性封装。
容易踩的坑:
- MySQL 5.7+ 才默认启用相关 instruments;8.0 默认开启,但若手动关过
memory/%类 instrument,该视图会为空 -
sys库是只读视图,不能INSERT/UPDATE,也不支持WHERE thread_id = ?精确过滤(需 JOINperformance_schema.threads) - 结果里
thread_id是 performance_schema 内部 ID,不是操作系统线程 PID(thread_os_id才对应top -H显示的 TID)
怎么查出“是谁、在跑什么、占了多少”?
执行这条 SQL 就能关联出完整上下文:
SELECT t.PROCESSLIST_USER AS `user`, t.PROCESSLIST_HOST AS `host`, t.PROCESSLIST_DB AS `db`, t.PROCESSLIST_COMMAND AS `cmd`, t.PROCESSLIST_STATE AS `state`, m.CURRENT_NUMBER_OF_BYTES_USED AS `bytes_used`, ROUND(m.CURRENT_NUMBER_OF_BYTES_USED/1024/1024, 2) AS `mb`, m.CURRENT_NUMBER_OF_ALLOCATIONS AS `allocs`, SUBSTRING_INDEX(t.PROCESSLIST_INFO, ' ', 10) AS `sql_snippet` FROM sys.x$memory_by_thread_by_current_bytes m JOIN performance_schema.threads t ON m.thread_id = t.thread_id WHERE t.PROCESSLIST_ID IS NOT NULL ORDER BY m.CURRENT_NUMBER_OF_BYTES_USED DESC LIMIT 5;
关键点:
- 用
sys.x$memory_by_thread_by_current_bytes(带x$前缀)避免视图内部额外计算开销,查得更快 -
PROCESSLIST_INFO可能很长,用SUBSTRING_INDEX(..., ' ', 10)截取前 10 个词,防爆屏 - 必须加
t.PROCESSLIST_ID IS NOT NULL过滤掉后台线程(如background),否则前几名常被 InnoDB purge 线程霸榜
查到高内存线程后,下一步该做什么?
拿到 top 1 的 thread_id 后,别急着 kill,先确认它是否真在“干坏事”:
- 看
PROCESSLIST_STATE:如果是Sorting result或Creating sort index,大概率是sort_buffer_size不够,导致落磁盘;如果是converting HEAP to MyISAM,说明临时表超限,要调tmp_table_size和max_heap_table_size - 查该线程正在执行的语句是否含
GROUP BY、ORDER BY、大结果集JOIN—— 这些是内存大户 - 用
SELECT * FROM performance_schema.events_statements_current WHERE THREAD_ID = ?\G看完整 SQL 和 digest,再结合EXPLAIN FORMAT=tree判断执行计划是否合理 - 注意:如果该线程
PROCESSLIST_TIME很小(
真正难缠的是那种 PROCESSLIST_TIME > 60 且 mb > 200 的线程——它可能卡在某个大排序或哈希连接里,既不结束也不释放内存,这时候才需要干预。











