只剩很少的可用磁盘空间,如何修改巨大的MySQL表

4
我在尝试修改一个庞大的(InnoDB)MySQL表时遇到了一些问题。该表的ID列(主键)定义为UNSIGNED INT,但已达到其最大值(4294967295)。
为了能够向此表添加更多行,我需要将此列的类型调整为BIGINT。然而,标准的MySQL ALTER命令(以及我到目前为止找到的任何其他解决方案)都会尝试生成具有新定义的新表,然后将所有数据复制到其中。对于这个表来说,这需要942.0Gb的可用磁盘空间,而我只有271Gb的可用空间(也没有其他分区可用所需的磁盘空间)。

是否有不需要完全复制原始表格的解决方案(而是将数据移动到新表格或类似的东西)?
我不介意在修改过程中无法访问表格,表格可以完全锁定数小时而不会出现问题(我目前无法使用它)。


购买更多的磁盘空间。如果表最初被分区,您将能够逐个分区进行工作。但由于您没有足够的空间,这将是一个挑战。 - Gordon Linoff
2个回答

4

鉴于您拥有271GB的可用磁盘空间,并且如果表在几个小时内没有被访问,您也可以使用以下步骤:

  1. 创建一个名为tbl_temp的新表,将ID设为BIGINT,并保持其余表结构完全相同。
  2. 创建一个简单的进程(使用任何服务器端脚本语言),从原始表中选择一行并将其插入到tbl_temp中。
  3. 删除从原始表中插入的行。
  4. 当所有行都被插入时,您的原始表将为空。删除原始表。
  5. tbl_temp重命名为原始表。

通过这种方式,您将能够在现有磁盘空间下迁移整个数据。


1

我接受了Samir的这个答案,因为在我看来这是最好的解决方案,但我用稍微不同的方式解决了问题。起初我没有想到我们有AWS账户和(CLI)访问S3的权限。所以我做了以下操作:

  1. 将(原始)表中的所有数据进行mysqldump,并直接流式传输到S3(因为我没有存储转储到本地所需的大量磁盘空间)。
    mysqldump -f --no-create-info --lock-tables db_name table_name | gzip -c | aws s3 cp - s3://bucket-name/mysqldump.sql.gz --expected-size 130608821125
  2. 将原始表的创建语句复制到记事本中(我使用的是notepad++)
  3. 删除原始表(是的,完全删除,以腾出新表的空间)
  4. 使用更新后的CREATE语句(实现我需要的新BIGINT定义),创建名字与原来一模一样的新表。CREATE new table, with exactly the same name as the original one, using an updated CREATE statement (implementing the new BIGINT definition I needed)
  5. 通过之前创建的转储填充新表中的所有数据:
    aws s3 cp s3://bucket-name/mysqldump.sql.gz - | gzip -d | mysql db_name
这种方法相较于Samir's answer更少出错,因为没有需要编写的脚本。
缺点是(我认为)整个过程需要更长时间,因为需要额外进行压缩、解压和网络传输。在我的情况下,完成整个过程大约需要5天,而我认为Samir的解决方案应该更快,这也是为什么我接受了它的原因。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接