我在localhost中使用mysql作为在r中执行统计的"查询工具",也就是说,每次运行r脚本时,我都会创建一个新的数据库(a),创建一个新的表(b),将数据导入b,提交一个查询以得到我需要的,然后我删除b和drop a。
它对我来说很好,但是我意识到ibdata文件的大小在快速增长,我在mysql中没有存储任何东西,但是ibdata1文件已经超过了100MB。
我正在或多或少地使用默认的mysql设置,是否有一种方法可以在固定的时间段后自动收缩/清除ibdata1文件?
- 进一步参考:配置innodb_file_per_表时,ibdata1呈指数增长。
ibdata1没有收缩是MySQL的一个特别恼人的特性。除非删除所有数据库、删除文件并重新加载转储,否则无法实际收缩ibdata1文件。
但您可以配置MySQL,使每个表(包括其索引)都存储为单独的文件。这样,ibdata1就不会长得这么大了。根据Bill Karwin的评论,默认情况下,从MySQL的5.6.6版本开始启用。
那是不久前我做的。但是,要设置服务器为每个表使用单独的文件,需要更改my.cnf以启用此功能:
1 2
| [mysqld]
innodb_file_per_table=1 |
http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html
当您想从ibdata1中回收空间时,实际上必须删除该文件:
对除mysql和performance_schema数据库外的所有数据库、过程、触发器等执行mysqldump操作。
删除除上述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 ENGINE=innodb或OPTIMIZE TABLE 可以从ibdata1中提取数据和索引页以分离文件。但是,除非执行上述步骤,否则IBdata1不会收缩。
关于information_schema,这是不必要的,也不可能下降。实际上,它只是一堆只读视图,而不是表。并没有和它们相关联的文件,甚至没有数据库目录。informations_schema正在使用memory db引擎,在mysqld停止/重新启动时会被丢弃并重新生成。请参阅https://dev.mysql.com/doc/refman/5.7/en/information-schema.html。
- 根据dev.mysql.com/doc/refman/5.1/en/&hellip,不需要"=1";
- 信息模式和性能模式怎么样?
- @JordanMagnuson我在一个测试服务器上尝试过,它不会让我(以mysql root/admin用户的身份登录)删除信息模式。所以,不。
- @JordanMagnuson不必费心删除信息模式。实际上,它只是一堆只读视图,而不是表。并且并没有和它们相关联的文件。甚至没有数据库的目录。Informations_模式正在使用内存数据库引擎,并在mysqld停止/重新启动时删除并重新生成。请参阅dev.mysql.com/doc/refman/5.5/en/information-schema.html。关于性能模式,我自己没有使用过这个模式。
- 有点交叉链接:stackoverflow.com/questions/3927690/…
- 我不知道这是否是最近发生的事情,但是一旦启用了innodb_file_per_table选项,您就可以简单地运行"alter tableengine=innodb"(即使它已经是innodb),它会将表移到它的单个文件中。不需要删除数据库等。
- 这很方便,但我认为它不会收缩ibdata1文件。该命令将把数据和索引页移动到一个单独的文件中,但ibdata1仍将保留元数据和缓冲区,并且仍然像以前一样占用足够的空间。
- +1 fwiw,mysql 5.6默认启用innodb_file_per_table。
- 无论出于什么原因,我都有ibdata1文件(大小约1GB),并且我有.ibd文件,它们代表我的每个数据库文件夹中的表。我不知道为什么两者都有,因为我设置了"innodb_file_per_table"选项。我假设如果不设置该设置,它就不会创建单独的文件。那么,即使设置了该选项,ibdata1文件也应该存在吗?
- 是的,IBdata1应该与其他文件一起出现。ibdata1文件仍将保存有关表、撤消日志和缓冲区的元数据。
- MySQL给我带来了严重的问题。我编辑了你的答案,希望不会发生在别人身上。i.stack.imgur.com/knxoo.png我转储了除mysql之外的所有数据库。注意到performance_schema上中间的错误吗?是的,嗯,我的BIG DUMP.SQL文件只包含之后的数据库。直到我把数据库掉了之后我才注意到…我刚刚丢失了15个数据库!
- 另外,在MySQL中,减少ibdata大小的最佳方法是什么?在数据库管理员那里。
- 但是,如果我优化了所有表(因此从ibdata文件中提取数据),我可以停止mysql、删除ibdata、启动mysql(这将重建ibdata文件)吗?还是桌子坏了?
- 由于ibdata1文件,我的服务器空间不足,所以我甚至无法转储数据库。如果只移动/var/lib/mysql处的文件(除了"mysql"、"ibdata1"、"ib_logfile0"和"ib_logfile1"),然后执行这些步骤,会是相同的吗?请参阅stackoverflow.com/questions/2482491/…
- 就像有些人说的,你不需要删除任何东西。正如我所理解的,您可以运行mysqlcheck -op database_name,这基本上只是运行alter tablemysql命令的另一种方式。如果你想去掉那个大的ibdata1文件,你还是需要删除一些东西。如果您不删除数据库并按照说明重新创建,您仍然会有一个大文件在那里不必要地占用空间。
- 这对我来说不太管用。在备份了我的表、删除了它们并删除了上面指定的文件之后,我无法恢复mysql服务器(我得到了:InnoDB: Error: space header page consists of zero bytes in data file ./ibdata1等等)。即使卸载和清除MySQL包也无法使其工作。我必须完全卸载并手动删除/var/lib/mysql目录,然后重新安装mysql。
- 对于200GB的数据库,备份到.sql转储并还原是完全不可行的。你有更好的解决方案吗?我不能把我的桌子换成myisam再换回来吗?
- 只是澄清一下:您需要将"innodb_file_per_table=1"放入您的文件中。innodb_file_per_table"是不够的。
- 使用Windows10上的服务器版本:5.7.14 mysql community server(gpl)作为wampserver的一部分。默认情况下不设置innodb_file_per_table。我只有一个大的ibdata1文件。也许默认设置仅适用于5.6.x版。
- 谢谢你的回答。实际上,不能删除信息模式。所以我们必须忽略它。
- 关于步骤1,这里有一个体面而快速的方法:stackoverflow.com/a/192044404/925058。另外,从dump重新导入时也可以采用相同的原则。
- 在bash中快速编写此答案的脚本,请参见下面的:stackoverflow.com/a/51543987/4904695
加上约翰·P的回答,
对于Linux系统,可以使用以下命令完成步骤1-6:
mysqldump -u [username] -p[root_password] [database_name] >
dumpfilename.sql。
江户十一〔一〕号
埃多克斯1〔2〕
埃多克斯1〔3〕江户十一〔四〕号(并删除可能命名为ib_logfile0、ib_logfile1等的任何其他ib_日志文件…)
江户十一〔七〕号
埃多克斯1〔8〕
埃多克斯1〔9〕
警告:如果此MySQL实例上有其他数据库,这些说明将导致您丢失其他数据库。确保修改步骤1、2和6、7以涵盖您希望保留的所有数据库。
- 对于每个具有innodb表的数据库,需要重复1、2和6。
- 你需要在5到6之间多走几步。您必须重新创建数据库并重新分配权限。所以从mysql客户端命令promptcreate database database_name;,然后从grant all privileges on database_name.* to 'username'@'localhost' identified by 'password';。
- @弗雷德,我做这件事时不需要授予特权。可能是因为我用相同的名称重新创建了数据库?
- 要在Password:提示下键入密码(这是一种更安全的做法),只需在没有任何实际密码的情况下输入-p。
- 触发器、事件和例程/函数不会被转储,除非您告诉mysqldump这样做。如果您的数据库中有任何一个包含--triggers、--events和--routines,也可以添加它们。另外,只需使用--all数据库一次转储所有数据库,而不是逐个转储。
- 现在这会导致错误InnoDB: File ./ibdata1: 'open' returned OS error 71. Cannot continue operation,因此无法重新启动服务器!
当您删除innodb表时,mysql不会释放ibdata文件中的空间,这就是它不断增长的原因。这些文件几乎不会缩小。
如何收缩现有的ibdata文件:
http://dev.mysql.com/doc/refman/5.5/en/innodb-resize-system-tablespace.html
您可以编写这个脚本,并安排脚本在固定的时间段后运行,但是对于上面描述的设置,多个表空间似乎是一个更简单的解决方案。
如果使用配置选项innodb_file_per_table,则创建多个表空间。也就是说,MySQL为每个表创建单独的文件,而不是一个共享文件。这些单独的文件a存储在数据库的目录中,当您删除此数据库时,它们将被删除。在您的情况下,这将消除收缩/清除ibdata文件的需要。
有关多个表空间的详细信息:
http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.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.
号
我认为你可以找到很好的解释和解决办法:
MySQL: Reducing ibdata1
在bash中快速编写接受答案的过程脚本:
1 2 3 4 5 6 7 8 9 10
| #!/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。
不包括mysql、information_schema、performance_schema(和binlog目录)。
假设您在/root/.my.cnf中有管理员凭证,并且您的数据库位于默认的/var/lib/mysql目录中。
您还可以在运行此脚本后清除二进制日志,以使用以下方法重新获得更多磁盘空间:
如果您的目标是监视MySQL的可用空间,并且您不能停止MySQL来收缩您的ibdata文件,那么可以通过table status命令来获取它。例子:
mysql>5.1.24:
1
| mysqlshow --status myInnodbDatabase myTable | awk '{print $20}' |
号
mysql<5.1.24:
1
| mysqlshow --status myInnodbDatabase myTable | awk '{print $35}' |
然后将该值与IBDATA文件进行比较:
。
来源:http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html
在新版本的mysql服务器中,上面的食谱将粉碎"mysql"数据库。在旧版本中,它起作用。在新的一些表中,切换到表类型innodb,这样做会损坏它们。最简单的方法是转储所有数据库,卸载mysql服务器,加载项保留my.cnf:
1 2 3 4 5 6 7
| [mysqld ]
innodb_file_per_table =1
erase all in /var /lib /mysql
install mysql -server
restore users and databases |
如前所述,您不能收缩ibdata1(要这样做,您需要转储和重建),但通常也没有真正的需要。
使用autoextend(可能是最常见的大小设置)IBdata1预分配存储,每次几乎满时都会增长。这使得写入速度更快,因为已经分配了空间。
删除数据时,它不会收缩,但文件中的空间标记为未使用。现在,当您插入新数据时,它将在进一步增长文件之前重用文件中的空白空间。
所以只有当你真正需要这些数据的时候,它才会继续增长。除非您实际需要另一个应用程序的空间,否则可能没有理由缩小它。
- 我觉得你对腾出空间的必要性有点太轻蔑了。
- 我有一个60Gig的固态分区。由于我使用的是4+Gig数据库,所以空间很快就用完了。我很快就要把MySQL移到另一个分区,但这个问题和它的答案会对我有所帮助。
- 谢谢你的回答,这很有帮助。我已经从旧数据中清除了一些表…很高兴知道磁盘的大小很快就不会再增长了。
- 我有一个500g的ibdata1文件——但是它中存储的几乎所有数据现在都存储在每个数据库文件中。我非常需要缩减这种浪费空间的座谈会!
- 完全是胡说八道!一个不断膨胀的文件需要修剪,不管你是否耗尽空间。我称之为storage leak。