应优先使用performance_schema.threads定位卡住线程,因其覆盖全生命周期;再结合data_lock_waits和data_locks查锁等待链与具体行锁;通过events_statements_summary_by_digest识别高频低耗时“微秒级雪崩”语句;并按需启用instrument、限制setup_actors/objects范围以避免自身性能损耗。

查哪个线程卡住了 performance_schema.threads + processlist 对比
直接看 SHOW PROCESSLIST 有时会漏掉刚启动就阻塞的线程,或者被 KILL 掉但还没彻底退出的“僵尸”连接。真正稳的入口是 performance_schema.threads,它记录所有线程生命周期,包括后台线程和内部任务。
实操建议:
- 先跑
SELECT THREAD_ID, NAME, TYPE, PROCESSLIST_STATE, PROCESSLIST_INFO FROM performance_schema.threads WHERE PROCESSLIST_ID IS NOT NULL AND PROCESSLIST_STATE != 'idle',筛出非空闲且有客户端 ID 的活跃线程 - 对比
information_schema.PROCESSLIST,若某线程在后者里已消失、但在前者中仍显示PROCESSLIST_STATE = 'Connecting' / 'Sending data' / 'Locked',大概率是网络断连未清理或锁等待超时未释放 -
NAME字段值如thread/sql/one_connection表示普通连接,thread/sql/main是主线程,别误杀
定位 SQL 级别锁等待 performance_schema.data_lock_waits
5.7+ 默认关闭数据锁监控,光看 INNODB_TRX 和 INNODB_LOCK_WAITS 不够细——它们不暴露行锁的 exact key,也看不到意向锁(IX/S)冲突源头。
实操建议:
- 确保已开启:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME = 'wait/lock/metadata/sql/mdl';和'wait/lock/innoDB/row_lock' - 查当前锁等待链:
SELECT * FROM performance_schema.data_lock_waits,重点关注BLOCKING_ENGINE_TRANSACTION_ID和REQUESTING_ENGINE_TRANSACTION_ID - 结合
performance_schema.data_locks查具体锁住哪张表哪行:SELECT OBJECT_SCHEMA, OBJECT_NAME, INDEX_NAME, LOCK_TYPE, LOCK_DATA FROM performance_schema.data_locks WHERE ENGINE_TRANSACTION_ID IN (xxx, yyy) - 注意:
LOCK_DATA是二进制格式,MySQL 8.0.24+ 才支持直接转成可读主键值;老版本只能靠EXPLAIN FOR CONNECTION xxx反推
识别隐式并发压力源 events_statements_summary_by_digest + timer_wait
慢查询日志只抓“慢”,但并发瓶颈常来自大量快速执行的小语句(比如每秒几千次 SELECT COUNT(*) FROM user WHERE status=1),单条不慢,加起来吃光 CPU 或 IO。
实操建议:
- 查高频低耗时语句:
SELECT DIGEST_TEXT, COUNT_STAR, SUM_TIMER_WAIT, AVG_TIMER_WAIT FROM performance_schema.events_statements_summary_by_digest ORDER BY COUNT_STAR DESC LIMIT 10 - 重点看
AVG_TIMER_WAIT在 1ms–10ms 区间、但COUNT_STAR > 1000/second的语句——这是典型的“微秒级雪崩”信号 - 若
DIGEST_TEXT显示大量SELECT ... WHERE ? = ?,说明应用没走连接池复用,或 ORM 自动生成了不可缓存的语句(比如带随机注释) - 不要只依赖
sys.schema_table_statistics视图,它聚合粒度太粗,丢失 digest 级别分布
避免 performance_schema 自身拖垮性能
开全量采集后,performance_schema 本身可能占 5%–15% CPU,尤其在高并发短连接场景下,setup_actors 和 setup_objects 配置不当会导致锁争用加剧。
实操建议:
- 禁止启用所有 instruments:
UPDATE performance_schema.setup_instruments SET ENABLED = 'NO', TIMED = 'NO';再按需打开关键项(如锁、语句、等待事件) - 限制采集范围:
INSERT INTO performance_schema.setup_actors VALUES ('localhost', 'app_user', '%', 'YES', 'YES');,避免监控系统账号和备份账号 - 定期清理历史:
TRUNCATE TABLE performance_schema.events_statements_history;(不是history_long,那个默认只存 1w 条) - MySQL 8.0.22+ 可设
performance_schema_consumer_events_statements_current = OFF,只留摘要表,省 30% 开销
最易被忽略的是 setup_objects 默认监控所有表,哪怕你只关心三张核心业务表,也要显式配置过滤,否则每次 DML 都触发全库元数据扫描判断是否该采集——这在分库分表环境特别伤。











