从表中删除数据行后,MySQL InnoDB不释放磁盘空间

时间:2022-09-24 10:46:34

I have one MySQL table using the InnoDB storage engine; it contains about 2M data rows. When I deleted data rows from the table, it did not release allocated disk space. Nor did the size of the ibdata1 file reduce after running the optimize table command.

我有一个使用InnoDB存储引擎的MySQL表;它包含大约2M数据行。当我从表中删除数据行时,它并没有释放分配的磁盘空间。在运行了优化表命令之后,ibdata1文件的大小也没有减少。

Is there any way to reclaim disk space from MySQL?

有没有办法从MySQL中回收磁盘空间?

I am in a bad situation; this application is running in about 50 different locations and now problem of low disk space is appearing at almost all of them.

我的处境很糟糕;这个应用程序在大约50个不同的位置运行,现在几乎所有的位置都出现了低磁盘空间的问题。

5 个解决方案

#1


121  

MySQL doesn't reduce the size of ibdata1. Ever. Even if you use optimize table to free the space used from deleted records, it will reuse it later.

MySQL没有减少ibdata1的大小。永远。即使使用优化表从已删除的记录中释放所使用的空间,它也将在以后重用它。

An alternative is to configure the server to use innodb_file_per_table, but this will require a backup, drop database and restore. The positive side is that the .ibd file for the table is reduced after an optimize table.

另一种方法是将服务器配置为使用innodb_file_per_table,但这将需要备份、删除数据库和恢复。积极的一面是,在优化表之后,表的.ibd文件减少了。

#2


30  

Just had the same problem myself.

我自己也有同样的问题。

What happens is, that even if you drop the database, innodb will still not release disk space. I had to export, stop mysql, remove the files manually, start mysql, create database and users, and then import. Thank god I only had 200MB worth of rows, but it spared 250GB of innodb file.

发生的情况是,即使删除数据库,innodb仍然不会释放磁盘空间。我必须导出,停止mysql,手动删除文件,启动mysql,创建数据库和用户,然后导入。感谢上帝,我只有200MB的行,但是它保留了250GB的innodb文件。

Fail by design.

失败的设计。

#3


20  

If you don't use innodb_file_per_table, reclaiming disk space is possible, but quite tedious, and requires a significant amount of downtime.

如果不使用innodb_file_per_table,回收磁盘空间是可能的,但是非常繁琐,并且需要大量的停机时间。

The How To is pretty in-depth - but I pasted the relevant part below.

How To是相当深入的——但是我粘贴了下面的相关部分。

Be sure to also retain a copy of your schema in your dump.

一定要在转储中保留模式的副本。

Currently, you cannot remove a data file from the system tablespace. To decrease the system tablespace size, use this procedure:

目前,无法从系统表空间中删除数据文件。要减小系统表空间大小,请使用以下步骤:

Use mysqldump to dump all your InnoDB tables.

使用mysqldump转储所有InnoDB表。

Stop the server.

停止服务器。

Remove all the existing tablespace files, including the ibdata and ib_log files. If you want to keep a backup copy of the information, then copy all the ib* files to another location before the removing the files in your MySQL installation.

删除所有现有的表空间文件,包括ibdata和ib_log文件。如果您希望保留信息的备份副本,那么在删除MySQL安装中的文件之前,请将所有ib*文件复制到另一个位置。

Remove any .frm files for InnoDB tables.

删除InnoDB表的任何.frm文件。

Configure a new tablespace.

配置一个新的表空间。

Restart the server.

重新启动服务器。

Import the dump files.

导入转储文件。

#4


0  

Other way to solve the problem of space reclaiming is, Create multiple partitions within table - Range based, Value based partitions and just drop/truncate the partition to reclaim the space, which will release the space used by whole data stored in the particular partition.

另一种解决空间回收问题的方法是,在基于表范围、基于值的分区中创建多个分区,然后删除/截断该分区以回收空间,从而释放存储在特定分区中的整个数据所使用的空间。

There will be some changes needed in table schema when you introduce the partitioning for your table like - Unique Keys, Indexes to include partition column etc.

当您为您的表引入分区时,比如—惟一键、包含分区列的索引等,表模式将需要一些更改。

#5


-1  

There are several ways to reclaim diskspace after deleting data from table for MySQL Inodb engine

在为MySQL Inodb引擎从表中删除数据之后,有几种方法可以回收磁盘空间

If you don't use innodb_file_per_table from the beginning, dumping all data, delete all file, recreate database and import data again is only way ( check answers of FlipMcF above )

如果您从一开始就不使用innodb_file_per_table,那么转储所有数据、删除所有文件、重新创建数据库和再次导入数据是唯一的方法(请查看FlipMcF的答案)

If you are using innodb_file_per_table, you may try

如果您使用innodb_file_per_table,您可以尝试。

  1. If you can delete all data truncate command will delete data and reclaim diskspace for you.
  2. 如果您可以删除所有的数据,截断命令将删除数据并为您回收磁盘空间。
  3. Alter table command will drop and recreate table so it can reclaim diskspace. Therefore after delete data, run alter table that change nothing to release hardisk ( ie: table TBL_A has charset uf8, after delete data run ALTER TABLE TBL_A charset utf8 -> this command change nothing from your table but It makes mysql recreate your table and regain diskspace
  4. Alter table命令将删除并重新创建表,以便它可以回收磁盘空间。因此,在删除数据之后,运行不更改任何内容的alter table来释放hardisk(即:table TBL_A有charset uf8,在删除数据后运行alter table TBL_A charset utf8 ->这个命令不会从表中更改任何内容,但会使mysql重新创建表并重新获取磁盘空间
  5. Create TBL_B like TBL_A . Insert select data you want to keep from TBL_A into TBL_B. Drop TBL_A, and rename TBL_B to TBL_A. This way is very effective if TBL_A and data that needed to delete is big (delete command in MySQL innodb is very bad performance)
  6. 创建TBL_B,如TBL_A。将要从TBL_A保存的select数据插入到TBL_B中。删除TBL_A,并将TBL_B重命名为TBL_A。如果TBL_A和需要删除的数据很大,这种方法非常有效(MySQL innodb中的delete命令性能非常差)

#1


121  

MySQL doesn't reduce the size of ibdata1. Ever. Even if you use optimize table to free the space used from deleted records, it will reuse it later.

MySQL没有减少ibdata1的大小。永远。即使使用优化表从已删除的记录中释放所使用的空间,它也将在以后重用它。

An alternative is to configure the server to use innodb_file_per_table, but this will require a backup, drop database and restore. The positive side is that the .ibd file for the table is reduced after an optimize table.

另一种方法是将服务器配置为使用innodb_file_per_table,但这将需要备份、删除数据库和恢复。积极的一面是,在优化表之后,表的.ibd文件减少了。

#2


30  

Just had the same problem myself.

我自己也有同样的问题。

What happens is, that even if you drop the database, innodb will still not release disk space. I had to export, stop mysql, remove the files manually, start mysql, create database and users, and then import. Thank god I only had 200MB worth of rows, but it spared 250GB of innodb file.

发生的情况是,即使删除数据库,innodb仍然不会释放磁盘空间。我必须导出,停止mysql,手动删除文件,启动mysql,创建数据库和用户,然后导入。感谢上帝,我只有200MB的行,但是它保留了250GB的innodb文件。

Fail by design.

失败的设计。

#3


20  

If you don't use innodb_file_per_table, reclaiming disk space is possible, but quite tedious, and requires a significant amount of downtime.

如果不使用innodb_file_per_table,回收磁盘空间是可能的,但是非常繁琐,并且需要大量的停机时间。

The How To is pretty in-depth - but I pasted the relevant part below.

How To是相当深入的——但是我粘贴了下面的相关部分。

Be sure to also retain a copy of your schema in your dump.

一定要在转储中保留模式的副本。

Currently, you cannot remove a data file from the system tablespace. To decrease the system tablespace size, use this procedure:

目前,无法从系统表空间中删除数据文件。要减小系统表空间大小,请使用以下步骤:

Use mysqldump to dump all your InnoDB tables.

使用mysqldump转储所有InnoDB表。

Stop the server.

停止服务器。

Remove all the existing tablespace files, including the ibdata and ib_log files. If you want to keep a backup copy of the information, then copy all the ib* files to another location before the removing the files in your MySQL installation.

删除所有现有的表空间文件,包括ibdata和ib_log文件。如果您希望保留信息的备份副本,那么在删除MySQL安装中的文件之前,请将所有ib*文件复制到另一个位置。

Remove any .frm files for InnoDB tables.

删除InnoDB表的任何.frm文件。

Configure a new tablespace.

配置一个新的表空间。

Restart the server.

重新启动服务器。

Import the dump files.

导入转储文件。

#4


0  

Other way to solve the problem of space reclaiming is, Create multiple partitions within table - Range based, Value based partitions and just drop/truncate the partition to reclaim the space, which will release the space used by whole data stored in the particular partition.

另一种解决空间回收问题的方法是,在基于表范围、基于值的分区中创建多个分区,然后删除/截断该分区以回收空间,从而释放存储在特定分区中的整个数据所使用的空间。

There will be some changes needed in table schema when you introduce the partitioning for your table like - Unique Keys, Indexes to include partition column etc.

当您为您的表引入分区时,比如—惟一键、包含分区列的索引等,表模式将需要一些更改。

#5


-1  

There are several ways to reclaim diskspace after deleting data from table for MySQL Inodb engine

在为MySQL Inodb引擎从表中删除数据之后,有几种方法可以回收磁盘空间

If you don't use innodb_file_per_table from the beginning, dumping all data, delete all file, recreate database and import data again is only way ( check answers of FlipMcF above )

如果您从一开始就不使用innodb_file_per_table,那么转储所有数据、删除所有文件、重新创建数据库和再次导入数据是唯一的方法(请查看FlipMcF的答案)

If you are using innodb_file_per_table, you may try

如果您使用innodb_file_per_table,您可以尝试。

  1. If you can delete all data truncate command will delete data and reclaim diskspace for you.
  2. 如果您可以删除所有的数据,截断命令将删除数据并为您回收磁盘空间。
  3. Alter table command will drop and recreate table so it can reclaim diskspace. Therefore after delete data, run alter table that change nothing to release hardisk ( ie: table TBL_A has charset uf8, after delete data run ALTER TABLE TBL_A charset utf8 -> this command change nothing from your table but It makes mysql recreate your table and regain diskspace
  4. Alter table命令将删除并重新创建表,以便它可以回收磁盘空间。因此,在删除数据之后,运行不更改任何内容的alter table来释放hardisk(即:table TBL_A有charset uf8,在删除数据后运行alter table TBL_A charset utf8 ->这个命令不会从表中更改任何内容,但会使mysql重新创建表并重新获取磁盘空间
  5. Create TBL_B like TBL_A . Insert select data you want to keep from TBL_A into TBL_B. Drop TBL_A, and rename TBL_B to TBL_A. This way is very effective if TBL_A and data that needed to delete is big (delete command in MySQL innodb is very bad performance)
  6. 创建TBL_B,如TBL_A。将要从TBL_A保存的select数据插入到TBL_B中。删除TBL_A,并将TBL_B重命名为TBL_A。如果TBL_A和需要删除的数据很大,这种方法非常有效(MySQL innodb中的delete命令性能非常差)