mysql 8.0.20+ 中对 innodb 表启用页压缩(如 compression='zlib')并配合 alter table 重建(指定 row_format=dynamic 和 key_block_size)可有效就地减容,但需满足 innodb_file_per_table=on、row_format 为 dynamic/compressed、无全文索引等前提;仅设压缩参数不释放空间,必须重建表;optimize table 对已压缩表冗余且有害;压缩效果取决于数据类型,文本类表收益显著。

MySQL磁盘空间不足时,直接对 InnoDB 表启用页压缩(COMPRESSION)是最有效的就地减容手段之一,但必须搭配碎片整理(OPTIMIZE TABLE 或 ALTER TABLE ... FORCE)才能真正释放磁盘空间给操作系统——光设压缩参数不会自动回收已分配的文件块。
确认表是否满足页压缩前提条件
页压缩(COMPRESSION='zlib' 等)只在 MySQL 8.0.20+ 生效,且要求:
-
innodb_file_per_table=ON(必须开启,否则无法单独压缩单表) -
innodb_file_format已被弃用,但需确保表使用Barracuda文件格式(可通过SHOW CREATE TABLE tbl_name查看ROW_FORMAT是否为DYNAMIC或COMPRESSED) - 表不能是
TEMPORARY表,也不能含全文索引(FULLTEXT)——否则ALTER TABLE ... COMPRESSION会报错ERROR 1030 (HY000): Got error -1 from storage engine - 若原表
ROW_FORMAT=COMPACT或REDUNDANT,需先ALTER TABLE ... ROW_FORMAT=DYNAMIC再设压缩,否则可能触发ERROR 1118 (42000): Row size too large
执行页压缩并强制重建表结构
页压缩本身不移动数据,必须通过重建表触发物理重写和空间回收。推荐用 ALTER TABLE 一次性完成格式切换与压缩设置:
ALTER TABLE logs_2025_q1 ROW_FORMAT=DYNAMIC, COMPRESSION='zlib', KEY_BLOCK_SIZE=8;
说明:
-
KEY_BLOCK_SIZE可选1/2/4/8/16(单位 KB),值越小压缩率越高,但 CPU 开销越大;一般从8起试,logs_2025_q1这类文本密集型表通常能压到 50%+ - 该语句会锁表(DDL 锁),大表建议在低峰期执行;如需在线压缩,MySQL 8.0.29+ 支持
ALGORITHM=INPLACE(仅限部分场景),但页压缩仍需拷贝数据,本质仍是重建 - 执行后检查实际效果:
SELECT table_name, data_length, data_free FROM information_schema.tables WHERE table_schema='your_db' AND table_name='logs_2025_q1';——data_free应显著下降,data_length也会缩小
压缩后必须运行 OPTIMIZE TABLE 才能释放磁盘?
不需要。页压缩 + ALTER TABLE 重建已经完成了碎片整理和空间回收,OPTIMIZE TABLE 对已压缩表是冗余操作,甚至可能因重复重建引发风险:
-
OPTIMIZE TABLE在 MySQL 8.0+ 默认等价于ALTER TABLE ... FORCE,它会再建一次表——压缩表重建开销更大,耗时翻倍,期间锁表时间更长 - 如果表原本就有大量
data_free(碎片),那压缩前的ALTER TABLE已经清掉了;若压缩后data_free仍高,说明压缩失败或数据本身不可压缩(如全是随机二进制) - 真正要检查的是
.ibd文件系统大小:du -h /var/lib/mysql/your_db/logs_2025_q1.ibd,而非information_schema的估算值
压缩失败常见报错与绕过方式
遇到 ERROR 1030 或 ERROR 1118 时,别急着放弃,优先排查这几个点:
- 字段含
TEXT/BLOB但innodb_strict_mode=ON:临时关掉再试:SET SESSION innodb_strict_mode=OFF;,执行完再开回 - 表有外键约束:先
SET FOREIGN_KEY_CHECKS=0;,压缩后再=1 -
KEY_BLOCK_SIZE设太小(如1)导致页内压缩失败:改用4或8重试 - 磁盘剩余空间不足原表大小的 1.2 倍:压缩过程需临时空间存新页,可先清理 binlog 或临时文件腾出空间
压缩不是万能解药,对数值型为主、无重复文本的表几乎无效;而对日志、JSON、HTML 类字段,往往一压就省下几十 GB——关键在选对表,而不是压得快。











