如何在MySQL中收缩/清除ibdata1文件

时间:2010-08-11 07:20:30

标签: mysql database innodb

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

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

我使用或多或少的默认MySQL设置进行设置,有没有办法可以在一段固定的时间后自动缩小/清除ibdata1文件?

8 个答案:

答案 0 :(得分:750)

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

但您可以配置MySQL,以便将每个表(包括其索引)存储为单独的文件。这样ibdata1就不会那么大。根据{{​​3}},默认情况下启用此版本的MySQL 5.6.6版本。

不久前我做到了这一点。但是,要将服务器设置为为每个表使用单独的文件,您需要更改my.cnf才能启用此功能:

[mysqld]
innodb_file_per_table=1

Bill Karwin's comment

如果你想从ibdata1回收空间,你实际上必须删除该文件:

  1. 执行mysqldump所有数据库,程序,触发器等mysqlperformance_schema数据库
  2. 删除除上述2个数据库
  3. 以外的所有数据库
  4. 停止mysql
  5. 删除ibdata1ib_log个文件
  6. 启动mysql
  7. 从转储中恢复
  8. 在步骤5中启动MySQL时,将重新创建ibdata1ib_log个文件。

    现在你很适合去。创建新数据库以进行分析时,这些表将位于单独的ibd*文件中,而不是ibdata1中。由于您通常不久后删除数据库,{@ 1}}文件将被删除。

    http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html

    你可能已经看到了这个:
    http://dev.mysql.com/doc/refman/5.1/en/drop-database.html

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

    关于OPTIMIZE TABLE <tablename>,这是不必要的,也不可能丢弃。它实际上只是一堆只读视图,而不是表。并且没有与它们相关联的文件,甚至也不是数据库目录。 information_schema正在使用内存db-engine,并在mysqld停止/重启时被删除并重新生成。请参阅http://bugs.mysql.com/bug.php?id=1341

答案 1 :(得分:42)

添加到John P's answer

对于Linux系统,可以使用以下命令完成步骤1-6:

  1. mysqldump -u [username] -p[root_password] [database_name] > dumpfilename.sql
  2. DROP DATABASE [database_name];
  3. sudo /etc/init.d/mysqld stop
  4. sudo rm /var/lib/mysql/ibdata1
    sudo rm /var/lib/mysql/ib_logfile (并删除任何其他可能被命名为ib_logfile0ib_logfile1等的ib_log文件...)
  5. sudo /etc/init.d/mysqld start
  6. create database [database_name];
  7. mysql -u [username]-p[root_password] [database_name] < dumpfilename.sql
  8. 警告:如果此mysql实例上有其他数据库,这些说明将导致您丢失其他数据库。确保修改步骤1,2和6,7以涵盖您希望保留的所有数据库。

答案 2 :(得分:33)

当你删除innodb表时,MySQL不会释放ibdata文件中的空间,这就是它不断增长的原因。这些文件几乎不会缩小。

如何缩小现有的ibdata文件:

http://dev.mysql.com/doc/refman/5.5/en/innodb-resize-system-tablespace.html

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

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

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

http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html

答案 3 :(得分:14)

  

如果你为你的(某些)MySQL表使用InnoDB存储引擎,你可能已经遇到了其默认配置的问题。您可能已经注意到MySQL的数据目录(在Debian / Ubuntu中 - / var / lib / mysql)中有一个名为“ibdata1”的文件。它几乎包含了MySQL实例的所有InnoDB数据(它不是事务日志),并且可能会变得非常大。默认情况下,此文件的初始大小为10Mb,并自动扩展。不幸的是,通过设计InnoDB数据文件无法收缩。这就是为什么DELETE,TRUNCATE,DROP等不会回收文件使用的空间。

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

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

答案 4 :(得分:7)

用bash快速编写接受答案的过程的脚本:

#!/usr/bin/env bash
DATABASES="$(mysql -e 'show databases \G' | grep "^Database" | grep -v '^Database: mysql$\|^Database: binlog$\|^Database: performance_schema\|^Database: information_schema' | sed 's/^Database: //g')"
mysqldump --databases $DATABASES -r alldatabases.sql && echo "$DATABASES" | while read -r DB; do
    mysql -e "drop database \`$DB\`"
done && \
    /etc/init.d/mysql stop && \
    find /var/lib/mysql -maxdepth 1 -type f \( -name 'ibdata1' -or -name 'ib_logfile*' \) -delete && \
    /etc/init.d/mysql start && \
    mysql < alldatabases.sql && \
    rm -f alldatabases.sql

另存为purge_binlogs.sh,然后以root运行。

排除mysqlinformation_schemaperformance_schema(和binlog目录)。

假设您在/root/.my.cnf中具有管理员凭据,并且数据库位于默认的/var/lib/mysql目录中。

您还可以在运行此脚本后清除二进制日志,以使用以下方法重新获得更多磁盘空间:

PURGE BINARY LOGS BEFORE CURRENT_TIMESTAMP;

答案 5 :(得分:6)

如果您的目标是监控MySQL可用空间,并且无法阻止MySQL缩小您的ibdata文件,那么请通过表状态命令获取它。例如:

MySQL&gt; 5.1.24:

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

MySQL&lt; 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

答案 6 :(得分:4)

在新版本的mysql-server食谱上面会粉碎&#34; mysql&#34;数据库。 在旧版本中它可以工作。在新的一些表中切换到表类型INNODB,这样做会损坏它们。 最简单的方法是转储所有数据库,卸载mysql-server, 加入了my.cnf:

[mysqld]
innodb_file_per_table=1


erase all in /var/lib/mysql
install mysql-server
restore users and databases

答案 7 :(得分:0)

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

使用autoextend(可能是最常见的大小设置)ibdata1预先分配存储空间,每次存储空间几乎已满。这使得写入速度更快,因为已经分配了空间。

删除数据时,它不会缩小,但文件中的空间会被标记为未使用。现在,当您插入新数据时,它会在文件中重复使用空格,然后再进一步增长文件。

因此,如果您确实需要这些数据,它只能继续增长。除非你真的需要空间用于其他应用程序,否则可能没有理由缩小它。