代码之家  ›  专栏  ›  技术社区  ›  Max Williams

快速删除巨型mysql列

  •  0
  • Max Williams  · 技术社区  · 6 年前

    当我们的rds mysql数据库实例空间不足时,我们今天遇到了一些站点紧急情况。这是因为我试图在一个有3000万行的数据库表中填充一个新添加的MediumText列。哎呀。

    我认为,使问题更加复杂的一件事是,当我意识到是什么使它耗尽了空间,杀死了 update 在这个过程中,我试着放下新的专栏,愚蠢地认为这会腾出一些空间。

    这实际上是不起作用的,因为当您在MySQL中删除一个列时,磁盘空间将无法恢复,至少在不做一些额外的维护工作的情况下不会恢复。

    但是,我认为通过增加数据库中临时文件的大小(可能是保存列数据的文件)实际上会使情况变得更糟,从而使进程具有可事务性—实际上,它就像一个废纸篓,为删除的数据提供可恢复性。

    这使得它的空间更为不足(我通过AWS控制台给了它更多的空间)。

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

    有没有一种方法可以快速删除列a)即使对于大表b)也不会生成任何额外的临时数据c)实际上会给您一些磁盘空间?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Bill Karwin    6 年前

    唯一的方法 减少 在不临时占用更多空间的情况下,存储的使用是删除表或截断表,即使这样,也只有在您有选择的情况下才会减少空间。 innodb_file_per_table=ON (这是自MySQL5.6以来默认启用的)。

    许多类型的alter table操作都会临时复制表,从而创建一个新的表空间。参照 https://dev.mysql.com/doc/refman/5.6/en/innodb-create-index-overview.html 注意每一种用“rebuilds table:yes”标记的alter table。

    重建表意味着创建一个新表,将旧表中的所有数据复制到新表中,同时适应新表中列的更改,然后将新表替换为旧表,最后删除旧表。对于一个大表来说,这需要时间,并且临时需要同时存储表和新表。

    基本上,任何更改行大小的更改,如添加/删除列、更改列的数据类型,甚至更改列的可空性,都会重建表。不可能快速或不临时使用更多空间就删除列。

    其他一些类型的alter表,比如删除次键,释放表空间中的数据库页,而不重建表。但这些页面仍然由表空间保存,并由后续数据或索引回收。

    表空间永远不会缩小。它只能在复制到新表空间时删除,或者进行碎片整理。

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