删除行会导致 MySQL 中的数据库存储增长

Posted

技术标签:

【中文标题】删除行会导致 MySQL 中的数据库存储增长【英文标题】:Deleting rows causes database storage to grow in MySQL 【发布时间】:2018-07-29 16:00:39 【问题描述】:

我刚刚观察到一些非常奇怪的事情,希望有人可以向我解释。我在 Linux 虚拟服务器上有一个带有 InnoDB 表的 mysql 5.5.58 数据库。其中一张表称为stats_archive,在普通用法中是只写的:它永远不会被读取或删除。其内容纯粹出于法律合规目的而保留一段时间,并且每月的 cronjob 应该删除旧条目。不幸的是,cronjob 默默地失败了,结果表被允许变得过大。今天早上我试图删除数据:

master:~# du -sh /var/lib/mysql
6.3G /var/lib/mysql

master:~# mysql -u root -p

mysql> select count(*) from stats_archive;
+-----------+
|  count(*) |
+-----------+
|  26339050 |
+-----------+
1 row in set (39.40 sec)

mysql> delete from stats_archive where archive_date < '2018-01-01';
Query OK, 24628026 rows affected (7 min 17.61 sec)

master:~# du -sh /var/lib/mysql
7.4G /var/lib/mysql

如您所见,MySQL 使用的存储空间增长了 1GB 多一点。当我这样做时,没有其他明显的数据库活动。删除不是在未提交的事务中完成的,所以数据库不应该仍然保留它以防我回滚。

/var/lib/mysql/ibdata1 使用了额外的 1GB 空间(不出所料),据我了解,这个文件永远不会缩小,所以I'm stuck with it until I can do something major 喜欢删除我所有的数据库,从备份中恢复并设置innodb_file_per_table=1(它目前不是)。我会在适当的时候这样做。

但我真正想知道的是为什么会发生这种情况,并且每次我从数据库中删除行时都会发生同样的情况吗?

注意:不是与this question 的重复。这个问题是关于未释放的存储,这在 InnoDB 中是众所周知的,与question I linked to 基本相同。我的问题是删除导致存储使用量增长显着。

【问题讨论】:

当您从表中删除行时。行空间将保留以供将来在该表中插入数据。要回收未使用的数据,请尝试优化表 Check here 不是与this question 的副本。这个问题是关于存储没有被释放的,这在 InnoDB 中是众所周知的。事实上,我什至链接到一个类似的问题。我的问题是删除导致存储使用量显着增长。那是完全不同的效果。请你重新打开这个问题,@Shadow。 不是效果不同,根本原因是一样的:innodb没有回收删除记录留下的空间。但是明白你的意思,你需要解释为什么会发生这种情况,而不是解决如何控制文件增长。 【参考方案1】:

即使您从中删除记录,InnoDB 表的大小也确实会增长。根本原因是 InnoDB 没有释放或回收已删除记录使用的空间这一已知事实(或错误)。

为了支持事务特性(回滚、一致读取等),InnoDB 采用了multi-versioning,这意味着它可以维护同一记录的多个版本。多个版本存储在 InnoDB 表空间的 undo log 部分中。撤消日志部分可以无限增长。

由于删除数据也是一种修改,以前版本的记录存储在撤消日志部分,导致文件大小显着增长。

【讨论】:

【参考方案2】:

(Shadow 很好地解释了为什么;我会谈谈现在该做什么。)

最好的办法是按周或月来PARTITION 表(只要有意义,并导致例如 20-60 个分区)。然后DROP PARTITION 而不是慢得多的DELETE。和REORGANIZE PARTITION 获得一个新的分区。更多详情here.

更好的方法是,在您刚刚的情况下,复制要保留的行。这是因为您只保留了 10% 的行;新表会小得多。有关如何执行 create-copy-rename 的更多讨论,请参阅 here

同时,您可以(花费几分钟的时间来整理桌子)通过OPTIMIZE TABLE 清理它。如果您不喜欢绑定它,请执行上面的 create-copy-rename。

【讨论】:

以上是关于删除行会导致 MySQL 中的数据库存储增长的主要内容,如果未能解决你的问题,请参考以下文章

从 UITableView 中删除行会导致部分标题问题?

从 .csv 文件中删除一些行会导致向其中添加 NaN 列

TIDB4业界使用情况

一口气看完MySQL--上篇

数据库mysql查询

MySQL5使用Innodb引擎时如何设置数据文件按表存储