将MySQL表列类型从INT更改为BIGINT

时间:2019-07-02 01:00:05

标签: mysql ruby-on-rails alter

我有一张表格,其中有不到5000万行。它达到了INT(2147483647)的限制。目前尚未写入表格。

我打算将ID列从INT更改为BIGINT。我正在使用Rails迁移来进行以下迁移:

  def up
    execute('ALTER TABLE table_name MODIFY COLUMN id BIGINT(8) NOT NULL AUTO_INCREMENT')
  end

我已经在2000行的数据集中进行了本地测试,效果很好。因为目前不使用该表,所以在5000万上运行ALTER TABLE命令应该可以吗?

我想在运行迁移之前进行检查。任何输入将不胜感激,谢谢!

1 个答案:

答案 0 :(得分:0)

我们的情况完全相同,但是使用了postgresql,我知道50M如何填充int的整个范围,它在id中的差距,随着时间的推移删除行而产生的差距或其他涉及不完整交易的因素等。

我将解释我们最终要做的事情,但是首先,认真地,在2k行中测试5000万行的数据迁移不是一个好测试。

针对此问题,可以有多种解决方案,具体取决于您使用的是哪个数据库提供商?。我们使用的是mazon RDS,它在运行时以及它们称为IOPS(输入/输出操作),如果我们在具有这样限制的数据库上运行如此密集的查询,它将在整个过程中用尽其IOPS配额,并且当IOPS配额用完时,数据库最终会变得太慢并且几乎没有用。我们不得不取消查询,并让IOPS赶上了大约30分钟到1小时的时间。

如果您没有这样的限制,并且在本地或类似地点拥有数据库,那么还有另一个因素,那就是,您是否可以承受停机时间?**

如果您可以承受宕机时间并且对数据库没有IOPS类型限制,则可以直接运行此查询,这将花费很多时间(可能需要半小时左右,具体取决于很多时间)的因素),同时

  • 随着行的更改,表将被锁定,因此不仅要确保该表在过程中没有任何写操作,而且没有任何读操作,以确保您的过程进入顺利结束,没有任何死锁类型的情况。

我们为避免停机和Amazon RDS IOPS限制所做的工作:

就我而言,当我们意识到这将用完时,表中还剩下约4000万个ID,并且我们希望避免停机。因此,我们采取了多步骤的方法:

  1. 创建一个新的big_int列,将其命名为new_id或其他名称(从开始就具有唯一索引),该列可以为null,默认为null。
  2. 编写每晚运行几次的后台作业,然后从new_id列回填id列。每天晚上我们回填大约4-5M行,并且在周末增加了很多(因为我们的应用程序在周末没有流量)。
  3. 当您遇到了回填问题时,现在我们将不得不停止对该表的任何访问(我们只是在晚上将应用关闭了几分钟),并从max(new_id)值开始创建了一个新序列,或使用现有序列并将其绑定到默认值为该序列的nextval的new_id列。
  4. 现在将主键从id切换到new_id,然后再使new_id不为空。
  5. 删除ID列。
  6. 将new_id重命名为id。
  7. 并恢复数据库操作。

以上内容仅是我们所做工作的最低限度的文字,您可以在Google上搜索一些不错的文章one is this。这种方法不是新方法,而且很常见,因此我相信您也可以找到特定于mysql的方法,或者您可以在上一篇文章中调整几项,您应该会做的很好。