直接看com_select、com_insert等累计值可算读写比例,但必须分引擎:myisam需结合key_reads/key_read_requests看索引缓存命中率,innodb则须交叉验证缓冲池读请求与脏页堆积情况,并辅以innodb_rows_*行级计数,避免仅凭语句数误判瓶颈。

直接看 Com_select、Com_insert、Com_update、Com_delete 四个变量的累计值,就能算出读写比例——但必须分引擎看待,因为 MyISAM 和 InnoDB 的锁机制、缓存路径完全不同,混在一起统计会掩盖真实瓶颈。
查 MyISAM 读写比例:重点盯 Key_reads 和 Key_read_requests
MyISAM 没事务,读写都走表级锁,它的“读写压力”不能只看 SQL 类型,更要看底层磁盘 I/O 是否被索引缓存扛住。关键指标是索引缓存命中率:
-
Key_read_requests是从 key_buffer 里读索引块的总次数,Key_reads是不得不从磁盘读索引块的次数 - 命中率 =
(1 - Key_reads / Key_read_requests) * 100%,低于 99% 就说明key_buffer_size配小了 - 如果
Key_reads在 5 分钟内增长 > 100 次,基本确认索引缓存严重不足,此时即使Com_select不高,实际读性能也已劣化 - 注意:MyISAM 的写操作(
Com_insert/Com_update)会触发Key_writes,但写缓存命中率意义不大,因为写最终都要刷盘
查 InnoDB 读写比例:用缓冲池请求 + 行操作计数交叉验证
InnoDB 的读写比例不能单靠 Com_select 和 Com_insert 算,因为大量读可能来自缓冲池内部访问(比如二级索引回表),而写可能被延迟刷脏页掩盖。必须结合两组指标:
- 读压力主看:
Innodb_buffer_pool_read_requests(缓冲池总读请求数) vsInnodb_buffer_pool_reads(真正读磁盘次数)。比值越低,说明读越“热”,哪怕Com_select数量不大 - 写压力主看:
Com_insert+Com_update+Com_delete的增量,再对照Innodb_buffer_pool_pages_dirty是否持续 > 1000 —— 如果脏页堆积,说明写入速度远超刷盘能力 - 别忽略
Innodb_rows_read/Innodb_rows_inserted这类行级计数,它们反映真实数据层吞吐,比语句计数更能暴露全表扫描或批量插入问题
为什么不能直接用 Questions / Uptime 算 QPS 再拆读写?
因为 Questions 包含存储过程内部语句、PREPARE/EXECUTE、甚至部分管理命令,而 Com_* 只统计客户端发起的原始 SQL。两者差值可能高达 20%~40%,尤其在用 ORM 或中间件的系统里:
-
Questions增长快 ≠ 业务读写多,可能是连接池频繁重连触发了COM_STATISTICS -
Com_select高但Innodb_rows_read低?大概率是走了覆盖索引,I/O 压力其实小 -
Com_update低但Innodb_row_lock_waits飙升?说明有少量高频更新正在争抢同一行,不是总量问题而是热点问题 - 线上环境禁用
innodb_status_output,它会把每秒的SHOW ENGINE INNODB STATUS输出打满错误日志,干扰真实错误排查
真正要判断读写失衡,得把语句层(Com_*)、引擎层(Innodb_* / Key_*)、I/O 层(Handler_read_*)三组指标对齐看——漏掉任何一层,都可能把慢查询归因为“写太多”,结果发现其实是 MyISAM 表的 .MYI 文件损坏导致每次 select 都要重建索引。











