mysql 8.0+ 的 page_compressed 表选项生效需同时满足:innodb 引擎、文件格式 barracuda、row_format 为 compressed 或特定条件下的 dynamic;key_block_size=8 仅在 innodb_file_per_table=on 且 innodb_page_size=16k 时有效;页压缩实际启用需通过 information_schema.innodb_tables 验证 row_format=compressed 且 space_type=single,并结合磁盘文件大小对比确认。

MySQL 8.0+ 的 PAGE_COMPRESSED 表选项实际生效条件是什么?
它不是开箱即用的压缩功能,必须同时满足三个硬性前提:使用 InnoDB 存储引擎、文件格式为 Barracuda、表行格式为 COMPRESSED 或 DYNAMIC(仅后者在开启 innodb_file_per_table=ON 且 innodb_page_size=16k 时可配合 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8 触发页压缩)。缺一不可,否则 CREATE TABLE ... ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8 看似成功,实际写入仍是未压缩页。
为什么 KEY_BLOCK_SIZE 设为 8 却没看到空间下降?
常见原因有三:
-
innodb_file_per_table必须为ON(默认值,但旧实例可能关着); -
innodb_file_format已被废弃,真正起作用的是innodb_file_per_table+innodb_page_size组合 —— 当前页大小为16k时,KEY_BLOCK_SIZE=8才有效;设为4或2会直接报错或静默降级; - 数据页必须“足够稀疏”才触发压缩:InnoDB 只对逻辑上能塞进更小物理页(如 8KB)的页面执行压缩,全满页不会拆分压缩,所以刚插入的数据往往看不出效果,需批量导入后
OPTIMIZE TABLE强制重建。
如何验证页压缩是否真实启用?
不能只看 SHOW CREATE TABLE,要查运行时元数据:
SELECT NAME, FILE_FORMAT, ROW_FORMAT, SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME LIKE 'your_db/your_table';
其中 ROW_FORMAT 显示 Compressed,且 SPACE_TYPE 为 Single(表示独立表空间),才算落地上线。再结合磁盘文件大小对比:ls -lh ./data/your_db/your_table.ibd 和同等数据量未压缩表对比,差异应达 30%–60%(取决于字段重复率和 NULL 比例)。
压缩后查询性能会变慢吗?
会,但可控。每次读取需解压页,写入需压缩页,CPU 开销上升;但若 I/O 是瓶颈(如机械盘、高延迟云盘),节省的读盘次数常抵消 CPU 成本。关键控制点:
- 避免在高并发短事务场景(如秒杀)中对热点表启用,解压争用可能放大锁等待;
-
innodb_read_io_threads和innodb_write_io_threads建议 ≥ 4,缓解压缩/解压队列积压; - 监控
Innodb_buffer_pool_pages_misc是否异常升高——压缩页在 buffer pool 中仍占整页空间,但实际磁盘只存压缩体,buffer pool 利用率估算会失真。
真正难处理的是压缩失败回退:当压缩后仍 >8KB,InnoDB 自动以原大小存储该页,不报错也不告警,只能靠定期比对 information_schema.innodb_metrics 中 compression_pad 类指标是否持续非零来间接判断。











