如何在不转储所有数据库的情况下缩小 innodb 文件 ibdata1?

rub*_*o77 24 mysql innodb memory disk-space

InnoDB 将所有表存储在一个大文件中ibdata1

删除大表后,无论表有多大,文件都会保持其大小。如何缩小该文件而不必转储并重新导入整个数据库(总共有数百 GB)?

我认为原因是因为您仍然可以回滚下降。就我而言,我不需要。

Rol*_*DBA 30

这是我多年来作为 MySQL DBA 和 DBA StackExchange 处理过的最具争议的话题之一。

要说得客气一点,根本就没有其他的办法来缩小ibdata1中。随着innodb_file_per_table禁用,每次运行时间OPTIMIZE TABLE上的InnoDB表,ibdata1中迅速成长。使用丢弃DROP TABLEDROP DATABASE无法回滚的数据,因为它们是 DDL,而不是 DML。我相信 Oracle 和 MSSQL 可以回滚 DDL。MySQL 无法做到这一点。

ibdata1 中有几类信息

  • 表格数据
  • 表索引
  • 表元数据
  • MVCC 控制数据
  • 双写入缓冲区(后台写入以防止依赖操作系统缓存)
  • 插入缓冲区(管理对非唯一二级索引的更改)

使用innodb_file_per_table=1将允许您使用在 ibdata1 之外创建的表数据和表索引来创建新表。您可以使用ALTER TABLE ... ENGINE=InnoDB;or提取仍在 ibdata1 中的任何表,OPTIMIZE TABLE但这会在 ibdata1 中留下巨大的未使用空间。

尽管如此,您必须清理 InnoDB 基础设施。我已经写过关于如何以及为什么这样做的 StackExchange 帖子:

好消息

您只需要转储数据,再重新加载一次,然后再也不重温这个问题OPTIMIZE TABLE之后运行确实会缩小.ibd任何 InnoDB 表的表空间文件。


Mic*_*bot 2

如果您不在 my.cnf 默认文件中使用以下设置,InnoDB 仅将所有 InnoDB 表存储在 ibdata1 中:

innodb_file_per_table = 1
Run Code Online (Sandbox Code Playgroud)

DROP TABLE(和 DROP DATABASE)无法回滚。

这不是不能缩小 ibdata1 的原因。

这是一个简短的解释,但 ibdata1 除了表数据之外还包含 InnoDB 内部结构。根据我的理解,要缩小它需要对其进行碎片整理,这不是受支持的操作。