必须开启innodb_file_per_table=on才能释放磁盘空间,否则drop/truncate表后ibdata1只增不减;唯一可信确认方式是执行show variables like 'innodb_file_per_table',返回on才生效,返回off则所有表仍写入共享表空间。

必须开启,否则 DROP TABLE 后磁盘空间永远不释放,ibdata1 只增不减。
怎么确认当前是否真开启了
别信版本文档说“默认开启”,SHOW VARIABLES LIKE 'innodb_file_per_table' 才是唯一可信依据。返回 ON 才算生效;返回 OFF 说明所有新表仍写进 ibdata1,你根本看不到任何 .ibd 文件。
- 该变量支持动态设置:
SET GLOBAL innodb_file_per_table = ON,但只影响后续新建的表 - 已有表不会自动迁移——哪怕你重启 MySQL、执行
OPTIMIZE TABLE或ALTER TABLE ... ENGINE=InnoDB,只要建表时innodb_file_per_table是OFF,数据就锁死在ibdata1里 - Linux 下检查物理文件:
ls -lh /var/lib/mysql/dbname/,若只有.frm没有.ibd,基本可判定该库下表仍在共享空间
为什么删了表,磁盘空间还是没回来
这是共享表空间最直接的代价:ibdata1 不会归还空间给操作系统,哪怕你 DROP TABLE 所有用户表,它体积也纹丝不动。因为里面混存着数据字典、undo 日志段、回滚段、change buffer 等全局结构,这些内容随事务持续增长,且无法在线清理。
-
DROP TABLE在共享模式下只是标记空间“可复用”,不是删除物理块 -
TRUNCATE TABLE同样不收缩ibdata1,性能优势也不存在 - 唯一能真正回收磁盘空间的操作:启用
innodb_file_per_table后新建表 + 对老表逐个执行ALTER TABLE t ENGINE=InnoDB(注意:重建期间需双倍磁盘空间)
开启后老表怎么搬出来
没有一键迁移命令。必须对每张存量表显式重建,才能把数据从 ibdata1 搬到独立 .ibd 文件中:
- 推荐语句:
ALTER TABLE table_name ENGINE=InnoDB或等价的OPTIMIZE TABLE table_name - 大表执行时间长,MySQL 5.6+ 虽支持 Online DDL,但仍会持有元数据锁(MDL),应用写入会阻塞
- 务必确认
innodb_file_per_table已为ON,否则重建完还是落回ibdata1 - 系统表(如
mysql.innodb_table_stats)强制驻留ibdata1,不要碰
真正缩小 ibdata1 的唯一办法
不能在线 shrink,也不能靠参数开关解决。如果 ibdata1 已膨胀到危险大小(比如 >100GB),唯一可靠路径是全库逻辑重建:
- 导出:
mysqldump -u root -p --all-databases --single-transaction --routines --triggers > full.sql - 停库,删掉
ibdata1、ib_logfile*、ibtmp1 - 配置文件明确写
innodb_file_per_table=1,确保无残留innodb_data_file_path - 启动 MySQL,再导入
full.sql
这个过程不可逆、不可中断,且所有表都会变成独立 .ibd。日常运维中,最容易被忽略的是:**开启参数只是起点,不是终点;看见 ON 就以为万事大吉,结果 ibdata1 还在默默涨——这才是线上最常踩的坑。**











