可通过show create table查row_format是否为dynamic/compressed,再结合information_schema.innodb_sys_columns中mtype=254且prtype&4096!=0判断字段是否溢出;溢出页不计入page_count,需通过file_size与data_length差值趋势分析估算。
怎么查 innodb_page_size 和实际行是否溢出
mysql 的 innodb 表如果单行数据超过 8kb(默认 innodb_page_size=16k 时,约 80% 页面空间用于存储,即 ~12kb 可用,但 blob/text/varchar 超长字段会触发行溢出),就会把大字段值存到单独的溢出页(overflow page),只在主页面留 20 字节指针。这不是错误,但会影响查询性能和统计准确性。
关键看两点:表是否启用了 ROW_FORMAT=DYNAMIC 或 COMPRESSED(只有这两种才支持真正的行溢出);以及字段是否真的被剥离出去了。
-
SHOW CREATE TABLE `your_table`查ROW_FORMAT,不是COMPACT或REDUNDANT - 执行
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME = 'db_name/your_table',确认ROW_FORMAT字段值 - 真正判断溢出:查
INFORMATION_SCHEMA.INNODB_SYS_COLUMNS中该表的列,看MTYPE和PRTYPE—— 若MTYPE=254(即VARCHAR)且PRTYPE & 4096 != 0,说明该列可能被溢出存储(需结合长度判断)
用 INFORMATION_SCHEMA.INNODB_SYS_INDEXES 看碎片页数量
表碎片不等于行溢出,但溢出页多、频繁 DELETE/UPDATE 大字段,会让碎片加剧。InnoDB 不直接暴露“溢出页数”,但可通过索引页统计反推:
-
INFORMATION_SCHEMA.INNODB_SYS_INDEXES中的PAGE_COUNT是该索引总页数,INNODB_SYS_TABLESPACES中对应表空间的FILE_SIZE/INNODB_PAGE_SIZE是物理分配页数,二者差值越大,碎片越严重 - 对主键索引(
INDEX_ID最小的那个)重点关注:若PAGE_COUNT远小于FILE_SIZE / 16384(假设默认页大小),说明有大量未回收的溢出页或已删除但未 purge 的记录 - 注意:
PAGE_COUNT不包含溢出页 —— 溢出页只记录在INNODB_SYS_TABLESPACES的FILE_SIZE里,但不会单独拆分统计
OPTIMIZE TABLE 能不能清理溢出行和碎片
能,但有条件。它本质是重建表(ALTER TABLE ... FORCE),会重新组织所有页,把溢出数据重写、合并,并释放空闲空间。
- 必须是
ROW_FORMAT=DYNAMIC或COMPRESSED,否则OPTIMIZE不会移动溢出列内容 - 执行后检查
INFORMATION_SCHEMA.TABLES.DATA_LENGTH是否明显下降,再对比DATA_FREE(空闲空间)是否归零或显著减少 - 线上慎用:会锁表(除非开启
innodb_fast_alter_table=ON且满足 ALGORITHM=INPLACE 条件),且大表耗时久;替代方案是ALTER TABLE t ENGINE=INNODB(效果等价,但语义更明确) - 如果
DATA_FREE仍很大,可能是innodb_file_per_table=OFF,此时碎片在共享表空间里,无法通过单表优化回收
为什么 ANALYZE TABLE 不更新溢出行统计
ANALYZE TABLE 只更新索引统计(如 Cardinality)和采样估算的行数,完全不扫描溢出页,也不读取 BLOB/TEXT 实际内容长度。所以它对溢出情况“视而不见”。
- 你看到的
AVG_ROW_LENGTH是基于主页面字段估算的,不含溢出部分,因此通常远低于真实平均行宽 - 想粗略估计溢出比例?用
SELECT AVG(LENGTH(blob_col)) FROM t对比AVG_ROW_LENGTH—— 若前者大很多,基本可判定溢出频繁 - 真正要监控,得靠定期采集
INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES.FILE_SIZE和INFORMATION_SCHEMA.TABLES.DATA_LENGTH做差值趋势分析,而不是依赖单次ANALYZE
溢出页本身不报错、不告警,但它让 SELECT * 变慢、让缓冲池压力变大、也让 mysqldump 导出体积虚高——这些才是你该盯住的实际信号。










