state为“waiting for row lock”或“locked”表明锁等待,与cpu无关;state为“sending data”或“copying to tmp table”且cpu接近100%,则属cpu/io瓶颈;“sleep”状态可能隐藏未提交事务持锁问题。

直接看 SHOW PROCESSLIST 里的 State 和服务器 CPU 使用率,就能快速区分——不是锁等待,就是 CPU(或 IO)瓶颈;两者不会同时是主因。
State 里出现 “Waiting for row lock” 或 “Locked” 就是锁等待
这类状态说明线程在等 InnoDB 行级资源,和 CPU 负载无关。常见组合:
-
State = "Waiting for row lock":事务 A 持有某行 X 锁,事务 B 正在等这行释放 -
State = "Locked":通常出现在 MyISAM 表或未提交事务导致的元数据锁(waiting for table metadata lock) -
State = "Sending data"或"Copying to tmp table":大概率不是锁问题,而是 SQL 执行本身慢(CPU/IO 高)
此时再跑 SELECT * FROM sys.innodb_lock_waits\G,如果有输出,blocking_trx_id 和 blocking_query 能立刻定位谁在阻塞你。
CPU 接近 100% 且 State 是 “executing” 或 “Sending data” 就是 CPU 瓶颈
这时候线程没卡在锁上,而是在拼命干活——但干得慢。典型信号:
-
top或htop显示mysqld进程 CPU 占用长期 >80% -
SHOW PROCESSLIST中大量线程State = "executing"或"Sending data",且Time值持续增长 - 这些线程执行的 SQL 往往没走索引、含复杂计算(如
ORDER BY RAND())、或关联太多表
注意:State = "Sending data" 容易误判为锁问题,但它实际表示“正在构造结果集”,可能是排序、聚合、临时表写入等 CPU 密集操作。
别被 “Sleep” 状态骗了
看似安静的 State = "Sleep" 连接,可能正在拖垮系统:
- 它背后可能是一个未提交的事务,持着行锁或 MDL 锁,让别人干等
- 查
information_schema.INNODB_TRX,看trx_started时间是否异常久,trx_state = "RUNNING"但trx_operation_state为空,基本就是“睡着了但没放手” -
performance_schema.events_statements_current能看到它最后执行的语句,常暴露真实问题(比如一个忘记COMMIT的BEGIN)
真正难缠的是锁等待和 CPU 瓶颈混在一起:比如一个大查询占满 CPU,导致事务提交变慢,进而延长持锁时间,引发连锁阻塞。这时候得先砍掉高 CPU 查询,再清理残留锁——顺序不能反。











