1

有人问过类似的问题,但我过去曾使用

ALTER TABLE tablename MODIFY columnname SMALLINT

我上次运行时发生了服务器崩溃,不得不恢复我的表。当表中有这么多数据时,使用此命令是否安全?如果有其他查询可能在表上并行运行怎么办?我应该复制表并在新表上运行查询吗?我应该复制列并将数据移动到新列吗?

请让我知道这样做时是否有任何最佳或“最安全”的做法。

另外,我知道这取决于很多因素,但是有谁知道查询应该在大约 550 万行(粗略估计)的 InnoDB 表上花费多长时间?有问题的列是 TINYINT,其中包含数据。我想升级到 SMALLINT 来处理更大的值。

谢谢!

4

4 回答 4

1

在速度较慢的磁盘上,并且表中有很多列,可能需要几个小时才能完成。

ALTER是“安全的”,因为它曾经执行以下操作:

  1. 锁定表
  2. 创建一个类似的表,但使用SMALLINT而不是TINYINT.
  3. 将所有行复制到新表中。
  4. 重命名表并删除旧表。
  5. 开锁

第 3 步是缓慢的部分。唯一的漏洞在第 4 步,速度非常快。

步骤 1-3 期间的服务器崩溃应该使旧表完好无损,但可能会留下一个部分创建的 tmp 表,名称类似于#sql....

Percona 的pt-online-schema-change优点是几乎无锁。

于 2016-09-13T21:23:12.200 回答
1

这不能轻易回答。

这取决于诸如

  • 表有自己的文件,还是与其他人共享?
  • 就字节而言,表有多大?

等等

它可以持续几分钟到几小时,并且可能涉及复制表的全部内容,因此您需要相当大的磁盘空间。

于 2016-09-13T14:23:37.970 回答
0

您可以向表中添加一个新的 SMALLINT 列:

ALTER TABLE tablename ADD columnname_new SMALLINT AFTER columnname;

然后将旧列中的数据复制到新列:

UPDATE tablename SET columnname_new = columnname WHERE columnname_new IS NULL LIMIT 100000

重复上述直到所有记录完成

然后你可以删除旧列:

ALTER TABLE tablename DROP COLUMN columnname

最后重命名新列:

ALTER TABLE tablename CHANGE columnname_new columnname SMALLINT

您可以将 100000 行的值从旧列复制到新列,以确保没有任何问题

于 2016-09-13T14:38:05.203 回答
0

我会添加一个新列,更改代码以检查新列中是否存在值,如果存在则读取/写入它。还要更改代码以从旧列读取并写入新列。此时您可以随意迁移数据,将旧列中的值复制到新列中,其中新列中不存在值。

迁移所有数据后,您可以删除旧列。

于 2016-09-13T14:58:13.523 回答