ibdata1无法缩小,唯一安全缩容方式是导出、初始化新实例并导入;开启innodb_file_per_table仅使新表使用独立.ibd文件,旧表需逐个执行alter table engine=innodb迁移,且必须双重验证配置生效。

磁盘爆满时,OPTIMIZE TABLE 很可能白跑一趟——它只对独立表空间生效,而你那张占了 80GB 的日志表大概率还在共享表空间 ibdata1 里,删库、删表、优化全不缩容。
先确认表是不是在独立表空间里
别急着执行任何优化命令,先查清楚这张表到底存在哪儿。InnoDB 表空间分两种:共享的 ibdata1(所有表挤一起)和独立的 .ibd 文件(每张表一个文件)。只有后者才能真正收缩。
- 运行:
SELECT TABLE_SCHEMA, TABLE_NAME, ENGINE, CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'your_table';—— 如果CREATE_OPTIONS为空或不含ROW_FORMAT,再查变量:SHOW VARIABLES LIKE 'innodb_file_per_table';,输出OFF就说明所有表都在ibdata1里 -
innodb_file_per_table = OFF是老配置遗留问题,MySQL 5.6+ 默认是ON,但升级或迁移后可能没重置 - 即使表结构显示
ROW_FORMAT=Dynamic,也不能代替innodb_file_per_table的实际值;ibdata1永远只增不减,DELETE或TRUNCATE都不释放物理空间
最快见效的是清理 binlog,不是删数据
线上环境 70% 的磁盘爆满源于未清理的 binlog。它不随 MySQL 重启消失,且默认永不过期(binlog_expire_logs_seconds = 0),一天就能涨几十 GB。
- 先看哪些 binlog 还能删:
SHOW BINARY LOGS;和SHOW MASTER STATUS;,记住当前正在写的文件名(如mysql-bin.000123),PURGE不能动它 - 安全清理命令:
PURGE BINARY LOGS TO 'mysql-bin.000122';或按时间删:PURGE BINARY LOGS BEFORE '2026-06-25 00:00:00'; - 如果删不动,可能是某个备份进程(如
mysqldump --master-data)还持有着旧 binlog 文件句柄,lsof -p $(pidof mysqld) | grep binlog找出并 kill 对应线程 - 设自动清理(MySQL 8.0):
SET GLOBAL binlog_expire_logs_seconds = 86400;(保留 1 天),避免反复手动操作
大表清理必须分两步:清数据 + 重建表
DELETE FROM logs WHERE created_at 后 <code>data_length 不变?正常。InnoDB 只标记页为“可复用”,不通知文件系统归还空间。
- 若表在独立表空间(
innodb_file_per_table = ON):DELETE完立刻跟OPTIMIZE TABLE your_table;,等效于ALTER TABLE your_table ENGINE=InnoDB;,会重建.ibd并真正缩小文件 - 若表太大怕锁太久(比如 >50GB),用
pt-osc在线改写:pt-online-schema-change --alter "ENGINE=InnoDB" D=your_db,t=your_table --execute,但需额外磁盘空间存临时表 - 如果只是想彻底清空,
TRUNCATE TABLE your_table;比DELETE快得多,但同样不会缩文件——仍需后续OPTIMIZE或ALTER ... ENGINE=InnoDB - 别用
DROP TABLE+CREATE替代,自增 ID、权限、外键约束都会丢失,风险远高于OPTIMIZE
ibdata1 已膨胀就只能导出重建
一旦确认 innodb_file_per_table = OFF,ibdata1 就成了黑洞:删库、删表、OPTIMIZE 全无效,物理文件大小纹丝不动。
- 唯一可靠路径:用
mysqldump --all-databases --single-transaction导出全部业务库(排除information_schema等系统库) - 停 MySQL,手动删掉
/var/lib/mysql/ibdata1、ib_logfile*、ibtmp1 - 修改配置文件,确保
innodb_file_per_table = ON,再启动 MySQL —— 它会新建一个仅含元数据的小ibdata1 - 导入 dump 文件。整个过程需停机,务必提前评估业务容忍窗口;RDS 用户无法直接操作文件系统,得走控制台“重建实例”流程
最常被忽略的点:清理完 binlog 或表后,df -h 看不到空间释放?检查是否还有未关闭的慢查询日志(slow_query_log_file)、错误日志(log_error)或临时文件(/tmp 下残留的 #sql-* 文件),它们也可能悄悄吃掉几十 GB。











