我在localhost中使用MySQL作为在R中执行统计的“查询工具”,也就是说,每次我运行R脚本时,我都会创建一个新的数据库(a),创建一个新的表(B),将数据导入到B中,提交一个查询以获得我需要的数据,然后我删除B和删除a。

这对我来说很好,但我意识到ibdata文件的大小正在迅速增加,我在MySQL中没有存储任何东西,但ibdata1文件已经超过100 MB。

我正在使用或多或少的默认MySQL设置进行设置,是否有一种方法可以让我在一段固定的时间后自动收缩/清除ibdata1文件?


当前回答

ibdata1不收缩是MySQL的一个特别烦人的特性。ibdata1文件实际上无法收缩,除非删除所有数据库、删除文件并重新加载转储。

但是您可以配置MySQL,使每个表(包括其索引)存储为一个单独的文件。这样ibdata1就不会变大。根据Bill Karwin的评论,MySQL 5.6.6版本默认启用了这个功能。

这是一段时间前的事了。然而,要设置你的服务器为每个表使用单独的文件,你需要改变my.cnf来启用这个功能:

[mysqld]
innodb_file_per_table=1

https://dev.mysql.com/doc/refman/5.6/en/innodb-file-per-table-tablespaces.html

当你想要从ibdata1中回收空间时,你实际上必须删除文件:

做一个mysqldump的所有数据库,过程,触发器等除了mysql和performance_schema数据库 删除除上述2个数据库以外的所有数据库 停止mysql 删除ibdata1和ib_log文件 启动mysql 从转储恢复

在第5步启动MySQL时,将重新创建ibdata1和ib_log文件。

现在你可以走了。在创建用于分析的新数据库时,表将位于单独的ibd*文件中,而不是ibdata1中。由于您通常很快就会删除数据库,ibd*文件将被删除。

http://dev.mysql.com/doc/refman/5.1/en/drop-database.html

你可能看过这个: http://bugs.mysql.com/bug.php?id=1341

通过使用命令ALTER TABLE <tablename> ENGINE=innodb或OPTIMIZE TABLE <tablename>,可以从ibdata1中提取数据和索引页,以分离文件。但是,除非执行上述步骤,否则ibdata1不会收缩。

对于information_schema,没有必要也不可能删除。它实际上只是一堆只读视图,而不是表。并且没有与它们相关的文件,甚至没有数据库目录。informations_schema使用内存db-engine,在停止/重新启动mysqld时删除并重新生成。见https://dev.mysql.com/doc/refman/5.7/en/information-schema.html。

其他回答

当你删除innodb表时,MySQL不会释放ibdata文件中的空间,这就是为什么它一直在增长。这些文件几乎从不缩小。

如何缩小现有的ibdata文件:

https://dev.mysql.com/doc/refman/5.6/en/innodb-system-tablespace.html#innodb-resize-system-tablespace

您可以编写脚本,并安排脚本在固定的时间后运行,但对于上面描述的设置,多个表空间似乎是更简单的解决方案。

如果使用配置选项innodb_file_per_table,则会创建多个表空间。也就是说,MySQL为每个表创建单独的文件,而不是一个共享文件。这些单独的文件存储在数据库的目录中,当您删除该数据库时,它们将被删除。在您的情况下,这样就不需要收缩/清除ibdata文件了。

关于多个表空间的更多信息:

https://dev.mysql.com/doc/refman/5.6/en/innodb-file-per-table-tablespaces.html

ibdata1不收缩是MySQL的一个特别烦人的特性。ibdata1文件实际上无法收缩,除非删除所有数据库、删除文件并重新加载转储。

但是您可以配置MySQL,使每个表(包括其索引)存储为一个单独的文件。这样ibdata1就不会变大。根据Bill Karwin的评论,MySQL 5.6.6版本默认启用了这个功能。

这是一段时间前的事了。然而,要设置你的服务器为每个表使用单独的文件,你需要改变my.cnf来启用这个功能:

[mysqld]
innodb_file_per_table=1

https://dev.mysql.com/doc/refman/5.6/en/innodb-file-per-table-tablespaces.html

当你想要从ibdata1中回收空间时,你实际上必须删除文件:

做一个mysqldump的所有数据库,过程,触发器等除了mysql和performance_schema数据库 删除除上述2个数据库以外的所有数据库 停止mysql 删除ibdata1和ib_log文件 启动mysql 从转储恢复

在第5步启动MySQL时,将重新创建ibdata1和ib_log文件。

现在你可以走了。在创建用于分析的新数据库时,表将位于单独的ibd*文件中,而不是ibdata1中。由于您通常很快就会删除数据库,ibd*文件将被删除。

http://dev.mysql.com/doc/refman/5.1/en/drop-database.html

你可能看过这个: http://bugs.mysql.com/bug.php?id=1341

通过使用命令ALTER TABLE <tablename> ENGINE=innodb或OPTIMIZE TABLE <tablename>,可以从ibdata1中提取数据和索引页,以分离文件。但是,除非执行上述步骤,否则ibdata1不会收缩。

对于information_schema,没有必要也不可能删除。它实际上只是一堆只读视图,而不是表。并且没有与它们相关的文件,甚至没有数据库目录。informations_schema使用内存db-engine,在停止/重新启动mysqld时删除并重新生成。见https://dev.mysql.com/doc/refman/5.7/en/information-schema.html。

如前所述,您不能收缩ibdata1(为此需要转储和重新构建),但通常也没有真正的必要。

使用autoextend(可能是最常见的大小设置),ibdata1预分配存储空间,在存储空间接近满时增长。这使得写入速度更快,因为已经分配了空间。

当你删除数据时,它不会缩小,但文件内部的空间被标记为未使用。现在,当您插入新数据时,它将在进一步增长文件之前重用文件中的空白空间。

所以只有当你真的需要这些数据时,它才会继续增长。除非您确实需要为另一个应用程序使用空间,否则可能没有理由缩小它。

如果您的目标是监视MySQL的空闲空间,而您又不能停止MySQL来缩小ibdata文件,那么可以通过表状态命令来获取它。例子:

MySQL > 5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $20}'

MySQL < 5.1.24:

mysqlshow --status myInnodbDatabase myTable | awk '{print $35}'

然后将这个值与ibdata文件进行比较:

du -b ibdata1

来源:http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html

If you use the InnoDB storage engine for (some of) your MySQL tables, you’ve probably already came across a problem with its default configuration. As you may have noticed in your MySQL’s data directory (in Debian/Ubuntu – /var/lib/mysql) lies a file called ‘ibdata1′. It holds almost all the InnoDB data (it’s not a transaction log) of the MySQL instance and could get quite big. By default this file has a initial size of 10Mb and it automatically extends. Unfortunately, by design InnoDB data files cannot be shrinked. That’s why DELETEs, TRUNCATEs, DROPs, etc. will not reclaim the space used by the file.

我想你可以在那里找到很好的解释和解决方案:

http://vdachev.net/2007/02/22/mysql-reducing-ibdata1/