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

时间:2018-02-19 12:02:24

标签: mysql innodb

我刚刚发现一些非常奇怪的东西,我希望有人可以向我解释。我在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多一点。当我这样做时,没有其他明显的数据库活动。删除操作未在未提交的事务中完成,因此如果我回滚,数据库仍然不能保留它。

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

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

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

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:2)

(Shadow对为什么给出了很好的解释;我会谈论现在要做什么。)

最好的办法是将表PARTITION按周或数月(无论什么都有意义,然后导致20-60个分区)。然后是DROP PARTITION,而不是慢得多DELETE。并REORGANIZE PARTITION获取新分区。更多详情here

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

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