快速删除巨型 MySQL 列的方法

Quick way to drop giant MySQL column

今天我们的 RDS MySQL 数据库实例 运行 超出 space 时,我们遇到了一些站点紧急情况。这是因为我试图在具有 3000 万行的数据库 table 中填充新添加的 MEDIUMTEXT 列。哎呀

我认为,使问题复杂化的一件事是,在我意识到是什么使它从 space 中变为 运行 并终止了 update 进程之后,我然后尝试删除新专栏,愚蠢地认为这样可以释放一些 space.

这实际上是行不通的,因为当您在 Mysql 中删除一列时,您不会取回磁盘 space,至少在不进行一些额外的内务处理的情况下是这样。

但是,我认为它实际上通过增加数据库中的临时文件的大小使事情变得更糟,大概是保存列数据,使过程 t运行 可操作 - 就像废纸篓一样,有效地为已删除的数据提供可恢复性。

这使它从 space 中增加了 运行(我通过 AWS 控制台给了它更多 space)。

所以,这不是一个美好的早晨(早上 7 点我的孩子们也在我耳边尖叫)。

有没有办法去掉一个列 a) 快速,即使对于大 tables b) 不会产生任何额外的临时数据 c) 实际上给你一些磁盘 space回来了?

减少 存储使用而不暂时占用更多 space 的唯一方法是删除 TABLE 或截断 TABLE,甚至只有当你有选项 innodb_file_per_table=ON 时才会减少 space (自 MySQL 5.6 以来默认打开)。

许多类型的 ALTER TABLE 操作会创建 table 的临时副本,从而创建新的 tablespace。参考 https://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html 并注意用 "Rebuilds table: Yes"

标注的每种类型的 ALTER TABLE

重建 table 意味着创建一个新的 table,将所有数据从旧的 table 复制到新的 table,同时适应列的变化新的 table,然后将新的 table 换成旧的 table,最后删除旧的 table。对于大 table,这需要时间,并且暂时需要同时存储 table 和新的 table。

基本上,任何更改行大小的更改,如 adding/dropping 列、更改列的数据类型,甚至更改列的可空性,都会重建 table。没有办法快速或不临时使用 more space.

来删除列

一些其他类型的 ALTER TABLE,例如删除辅助键,释放 tablespace 中的数据库页面,而不重建 table。但这些页面仍由 tablespace 持有并由后续数据或索引回收。

A tablespace 永不缩小。它只能被删除,或者在复制到新的 tablespace.

时进行碎片整理

因此,您需要确保至少有足够的可用磁盘 space 来存储您最大的 table 的第二个副本(如果它们存储在同一卷上,则加上二进制日志,但我不知道RDS是否将binlog存储在同一个卷上。