应结合information_schema.INNODB_METRICS(取两次快照差值算页级读写比)、SHOW ENGINE INNODB STATUS(查事务堆积与锁等待)和SHOW GLOBAL STATUS(统计SQL命令级读写分布)多维度动态分析,不可单一看Threads_running或静态比例。
查 information_schema.INNODB_METRICS 看实时读写比例
mysql 5.6+ 的 innodb_metrics 表能直接反映 innodb 层的逻辑读写行为,比单纯看 qps 更贴近真实负载。它统计的是「页级」操作,比如 innodb_buffer_pool_read_requests(逻辑读)和 innodb_buffer_pool_write_requests(逻辑写),二者比值就是实际读写比例。
实操建议:
- 用
SELECT NAME, COUNT FROM information_schema.INNODB_METRICS WHERE NAME IN ('buffer_pool_read_requests', 'buffer_pool_write_requests');查当前累计值,差值法算短时间窗口比例(比如每 5 秒采一次) - 注意:这些计数器是全局累加、不可重置,不能直接用单次查询值做比例;必须取两次快照再相减
-
buffer_pool_read_requests包含命中 buffer pool 的读,不等于物理 I/O;若想看磁盘压力,得盯innodb_buffer_pool_reads(真正从磁盘读的次数) - 该表默认多数指标是 DISABLED 状态,需先执行
SET GLOBAL innodb_monitor_enable = 'buffer_pool_read_requests,buffer_pool_write_requests';
用 SHOW ENGINE INNODB STATUS 抓事务状态快照
这个命令输出里 TRANSACTIONS 部分包含当前活跃事务数、等待锁的事务、回滚段使用量等关键现场信息,是判断高并发下事务是否堆积、卡死的最快手段。
实操建议:
- 重点看
Trx id counter增速(反映事务提交频率)、History list length(越大说明 purge 滞后越严重,可能拖慢 SELECT) - 出现大量
LOCK WAIT行时,立刻检查*** (1) WAITING FOR THIS LOCK TO BE GRANTED:后面的锁对象,结合INFORMATION_SCHEMA.INNODB_TRX和INNODB_LOCKS定位阻塞源 - 别依赖单次输出——高并发下状态瞬息万变,要用脚本循环执行(如
while sleep 1; do mysql -e "SHOW ENGINE INNODB STATUS\G" >> status.log; done),再人工或 grep 筛关键字段 - 注意:该命令会短暂加全局读锁,生产环境高频调用可能影响性能,建议间隔 ≥1s
监控 Com_select/Com_insert/Com_update/Com_delete 的增量比
这是最轻量、兼容性最好的读写比例估算方式,直接来自 SHOW GLOBAL STATUS,适用于所有 MySQL 版本,也适合嵌入监控系统(如 Prometheus + mysqld_exporter)。
实操建议:
- 用
SHOW GLOBAL STATUS LIKE 'Com_%'获取全部命令计数,重点关注Com_select(读)、Com_insert(写)、Com_update(写)、Com_delete(写)四项 - 读写比 =
Com_select / (Com_insert + Com_update + Com_delete);但要注意:一个UPDATE可能更新多行,而SELECT可能只查一行,数值比 ≠ 实际资源消耗比 - 如果应用大量使用存储过程或触发器,
Com_*计数可能低估真实 DML 量(因为部分逻辑在服务端执行,不走客户端命令路径) - 该指标无法区分长事务中的空闲等待,也不能反映锁竞争——只能告诉你“SQL 类型分布”,不是“负载压力分布”
为什么不能只看 Threads_running 判断并发压力
Threads_running 显示当前非睡眠态连接数,很多人误以为它等于活跃事务数,其实不然。它包含正在解析 SQL、排序、发送结果、甚至网络写阻塞的线程,和事务生命周期无直接对应关系。
实操建议:
- 当
Threads_running持续 > 50 且innodb_row_lock_time_avg同步升高,才值得怀疑是锁争用导致的假性“高并发” - 对比
INNODB_TRX中trx_state = 'RUNNING'的数量,才能知道真正持有事务的线程有多少;很多Threads_running其实刚执行完语句、还没 commit,事务已结束 - 某些 ORM(如 Django)默认开启 autocommit,每个 SQL 都是独立事务,
Threads_running高但INNODB_TRX为空——此时不是并发问题,而是客户端连接池配置过松或 SQL 效率低 - 这个变量对连接复用(如连接池)敏感,同一连接反复执行不同 SQL 也会让
Threads_running波动,不能单独作为扩容依据
高并发下的读写比例和事务状态从来不是静态数字,而是多个指标在不同粒度(SQL 层、引擎层、OS 层)的动态映射。最容易被忽略的是:同一个业务请求,在不同缓存命中率、不同索引选择、不同隔离级别下,对 InnoDB 的压力模式可能完全不同。测的时候,得把应用请求链路切片,再逐层对齐指标口径。

















