改innodb_page_size无效,因溢出页固定16KB且硬编码;仅DYNAMIC/COMPRESSED格式启用溢出机制,性能瓶颈在于溢出页引发的随机I/O。

不能靠调整 innodb_page_size 来缓解行溢出问题——它对溢出页大小完全无效。
为什么改 innodb_page_size 没用
InnoDB 的溢出页(overflow page)固定为 16KB,和 innodb_page_size 参数值无关。即使你把 innodb_page_size 设成 4KB 或 64KB(需初始化时指定,运行中不可改),溢出页依然按 16KB 分配和读取。
这个设计是硬编码在源码里的,不是配置项可调的逻辑分支。所以试图通过调大页尺寸来“塞下更多大字段”,属于方向性误解。
-
innodb_page_size只影响聚簇索引页、二级索引页等常规数据页的尺寸 - 溢出页走的是独立分配路径,底层调用
fil_space_create时直接写死UNIV_PAGE_SIZE为 16KB - MySQL 8.0+ 也未开放溢出页尺寸配置接口
真正触发溢出的条件是什么
行溢出是否发生,取决于 ROW_FORMAT 和单行实际存储体积,和页大小无直接关系:
- 仅
ROW_FORMAT = DYNAMIC或COMPRESSED才启用溢出页机制;COMPACT和REDUNDANT会把前 768 字节留在主记录里,其余截断或拼接进相邻页,更容易导致页分裂 - 判断依据不是“字段定义长度”,而是该行所有列实际字节总和 + 行头开销(约 20–30 字节)是否超过页内可用空间(约 8KB 左右)
- 例如:一个
VARCHAR(1000)字段存了 900 字节 UTF8MB4 文本(3 字节/字符 → 实际 2700 字节),加上其他字段,就可能触发溢出
查确认是否真有溢出,别猜
肉眼看不到溢出页是否存在,得靠实证:
- 用
SELECT LENGTH(col), LENGTH(col) > 8000 FROM t WHERE id = ?看单字段是否超阈值 - 查建表语句:
SHOW CREATE TABLE t,确认ROW_FORMAT是DYNAMIC而非COMPACT - 用
mysqlpump --no-data或mysqldump --no-data输出 DDL,比对ROW_FORMAT和字符集 - 极端情况可查
INFORMATION_SCHEMA.INNODB_SYS_TABLES中的row_format字段,但需有 PROCESS 权限
性能瓶颈其实卡在随机 I/O 上
一旦用了溢出页,每次读取大字段都会多一次同步单页读(os_aio):
- 执行
SELECT col FROM t WHERE id = 1时,InnoDB 先读聚簇索引页拿到 20 字节指针,再根据指针发起一次磁盘随机读 - SSD 上单次随机读约 0.1ms,HDD 上可能达 10ms+;高并发时容易堆积在
os_aio等待队列 - 这比改
innodb_page_size影响大几个数量级——后者只影响缓冲池利用率和内存对齐,不解决溢出本质
真正要优化,得从字段类型、ROW_FORMAT、访问模式入手,而不是碰那个改不了也帮不上忙的 innodb_page_size。











