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


24

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

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

我认为原因是因为您仍然能够回滚删除。就我而言,我不需要。

Answers:


30

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

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

ibdata1中驻留了几类信息

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

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

尽管如此,您仍必须清理InnoDB基础结构。我已经写了StackExchange帖子,介绍如何以及为什么这样做:

好消息

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


1
较小的更正:MSSQL和PostgreSQL可以回滚DDL。Oracle不能。实际上,Oracle在看到DDL时会发出隐式提交!
克里斯·特拉弗斯

1
@RolandoMySQLDBA既然这个自动收缩的“好消息”适用于哪个版本的MySQL?
Gavriel

@Gavriel-我想你读错了。您仍然必须转储;除去ibdata1; 重新开始; 并重新加载。ibdata1不会自动收缩。(更改iblog *现在更加简单。)
Rick James

2

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

innodb_file_per_table = 1

DROP TABLE(和DROP DATABASE)不能回滚。

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.