SHOW PROFILE BLOCK IO 不可靠,Block_gets 仅统计 read() 系统调用次数而非真实磁盘读页数;应使用 performance_schema.events_waits_history_long 中 wait/io/file/innodb/innodb_data_file 事件行数或 Innodb_buffer_pool_reads 指标定位物理 IO。

SHOW PROFILE BLOCK IO 不再可靠,别再依赖它查真实磁盘读写
MySQL 8.0+ 中 SHOW PROFILE 已被官方标记为 deprecated,且即使在 5.7 中启用,SHOW PROFILE BLOCK IO FOR QUERY N 返回的 Block_gets 也不是物理读页数——它只是 read() 系统调用次数,哪怕数据全在 page cache 里也会计数。真要抓“从磁盘读了多少 16KB 页”,得绕过这个假指标。
为什么 Block_gets ≠ 物理磁盘读页数
根本原因在于 Linux 的 VFS 层抽象:Block_gets 统计的是存储引擎发起的 read() 系统调用次数,而内核会先查 page cache;命中就直接返回内存数据,根本不触碰磁盘。所以你看到 Block_gets = 120,实际物理 IO 可能是 0。
-
Block_gets高 +Innodb_buffer_pool_reads = 0→ 全部命中 buffer pool,无磁盘 IO -
Block_gets低 +Innodb_buffer_pool_reads每秒几十次 → SQL 单次逻辑简单(比如点查),但 Buffer Pool 太小,每次都要单独拉一页,IO 密集型瓶颈藏在这里 - 想验证是否真读盘?看
performance_schema.events_waits_history_long中wait/io/file/innodb/innodb_data_file事件行数 —— 每行 = 至少一次物理读页
如何用 performance_schema 查单条 SQL 的真实磁盘读页数
前提是 performance_schema 已启用(SELECT @@performance_schema 返回 1),且等待事件消费者已打开:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_waits%';
执行目标 SQL 后,立即查当前连接的最近等待事件:
SELECT EVENT_NAME, TIMER_WAIT FROM performance_schema.events_waits_history_long WHERE THREAD_ID = (SELECT THREAD_ID FROM performance_schema.threads WHERE PROCESSLIST_ID = CONNECTION_ID()) AND EVENT_NAME LIKE 'wait/io/file/innodb/innodb_data_file' ORDER BY TIMER_START DESC LIMIT 20;
- 匹配行数 ≈ 物理读页数(每次
read()至少读 1 页,极端情况如 partial page read 可能略多) -
TIMER_WAIT是皮秒单位,除以1000000000得毫秒,但别太依赖它——慢不等于读盘多,快也不等于没读盘 - 注意过滤
innodb_log_file事件,它反映 redo log 写入,不是数据页读取
Handler_read_* 和 Innodb_buffer_pool_reads 到底怎么看
这两个指标常被误读:
-
Handler_read_first、Handler_read_key、Handler_read_next:全是引擎接口调用次数,在内存中完成。Buffer Pool 命中率 100%,它们照样涨 -
Handler_read_rnd_next高 ≠ 扫磁盘,只代表“按行指针取下一行”,取的可能是刚载入的页里的下一行 -
Innodb_buffer_pool_reads才是硬指标:每发生一次,InnoDB 就从磁盘同步读入一个数据页(16KB)到 buffer pool - 如果该值持续 > 100/s,且
Innodb_buffer_pool_read_requests远大于它,说明 Buffer Pool 不够用,innodb_buffer_pool_size该调大了
真正卡住数据库的,从来不是“逻辑读了多少行”,而是“物理读了多少页”。盯住 performance_schema 的底层 wait 事件,或者长期监控 Innodb_buffer_pool_reads 的速率,比翻 SHOW PROFILE 有用得多。


















