简体   繁体   English

MySql InnoDB 上的数字类型迁移

[英]MySql Numeric Type Migration on InnoDB

We have a very large (10million+) row table stored in MySql using the InnoDB engine.我们使用 InnoDB 引擎在 MySql 中存储了一个非常大的(超过 1000 万)行表。 Column 'x' is defined as 'smallint(5) unsigned not null'.列“x”被定义为“smallint(5) unsigned not null”。

Requirements have now changed since the original design a few years ago, and column 'x' needs to store a minimum datatype size of 'int unsigned not null'.自几年前的原始设计以来,要求现在已经改变,并且列“x”需要存储最小数据类型大小“int unsigned not null”。

We are allowed a "short" downtime to deploy the application (less than 5 mins) so any database change would need to fit within this time window if it requires the database table to be made temporarily unavailable in any way (eg full table lock).我们允许“短”停机时间来部署应用程序(少于 5 分钟),因此如果需要以任何方式使数据库表暂时不可用(例如全表锁定),任何数据库更改都需要在此时间内适应. If the change can be done "online" then we can probably accept degraded performance for a longer period.如果更改可以“在线”完成,那么我们可能会在更长的时间内接受性能下降。

Has anyone here had experience of altering column type in MySql/InnoDB on a very large table?这里有没有人有在非常大的表上更改 MySql/InnoDB 中的列类型的经验? If so, did it go OK and roughly how long did it take (I realise this is hardware dependent, I am just trying to understand if what we are asking to do in the time window is even vaguely possible)?如果是这样,它是否 go 好,大约花了多长时间(我意识到这取决于硬件,我只是想了解我们是否要求在 window 甚至模糊可能的时间内做什么)?

Thanks in advance,提前致谢,

heres a recipe i've used这是我用过的食谱

where you have old column, a你有旧专栏的地方,一个

  1. create a new column b创建一个新列 b
  2. create a trigger to update b on update/insert on a创建触发器以在更新/插入 a 时更新 b
  3. update b = a更新 b = a
  4. drop all fkey relations referencing a删除所有引用 a 的 fkey 关系
  5. create fkey relations for b为 b 创建 fkey 关系
  6. update code to use column b instead of a (deploy)更新代码以使用列 b 而不是 a(部署)
  7. drop triggers on column a在列 a 上删除触发器
  8. drop column a删除列 a

repeat all steps if you must change the column name back.如果您必须更改列名,请重复所有步骤。

You could do it online by creating a new table as a clone of the original's layout.您可以通过创建一个新表作为原始布局的克隆来在线执行此操作。

CREATE TABLE newtable LIKE oldtable;

Next, alter your new table's columns to meet the new spec接下来,更改新表的列以满足新规范

ALTER TABLE newtable ... ;

Once that's done, copy the data.完成后,复制数据。

INSERT INTO newtable SELECT * FROM oldtable;

Finally, use your few minutes downtime to rename your old table to something else, then give your new table the old table's name.最后,利用几分钟的停机时间将旧表重命名为其他名称,然后为新表指定旧表的名称。

Of course, you need to have enough storage for two copies of your table available.当然,您需要有足够的存储空间来存放两个可用的表副本。 Also, you might want to disable the indexes on the new table when doing the copy to reduce stress on the server during the copy operation.此外,您可能希望在执行复制时禁用新表上的索引,以减少复制操作期间服务器的压力。

Once you're confident that all the data in the old table has been copied to the new without any lossage you can finally delete the old table entirely.一旦您确信旧表中的所有数据都已复制到新表中而没有任何损失,您最终可以完全删除旧表。

EDIT:编辑:

Actually, a better approach might be to just add a new column to your existing table that meets the new requirements for the column you want to update, copy the values of the old column to the new column, drop the old column and rename the new column to the old column's name.实际上,更好的方法可能是在现有表中添加一个满足要更新的列的新要求的新列,将旧列的值复制到新列,删除旧列并重命名新列列到旧列的名称。 It would certainly put lower demands on your storage.它肯定会对您的存储提出更低的要求。

Also, if you have any FK constraints that depend on the column in question, you will need to remove them before starting and reinstate them on the new column once you've done.此外,如果您有任何依赖于相关列的 FK 约束,则需要在开始之前删除它们,并在完成后在新列上恢复它们。

What kind of high-availability solution do you currently have in place?您目前有什么样的高可用性解决方案?

I ask because, 5 minutes is not enough downtime to allow a reboot for normal tasks such as OS updates.我之所以这样问,是因为 5 分钟的停机时间不足以让正常任务(例如操作系统更新)重新启动。

You must therefore, have some kind of high-availability solution in place to allow these regular (I assume your operations team continues to apply patches from time to time) updates.因此,您必须拥有某种高可用性解决方案来允许这些定期(我假设您的运营团队继续不时应用补丁)更新。

It should be possible to use such a system to do this.应该可以使用这样的系统来做到这一点。

However, ALTER TABLE allows the table to remain available for read operations throughout its run, and only blocks reads for a short time at the end (much less than five minutes on most systems).但是,ALTER TABLE 允许表在其整个运行过程中保持可用于读取操作,并且在结束时仅阻塞读取一小段时间(在大多数系统上少于五分钟)。

So ask, what time can you reasonably block writes for?所以问,你什么时候可以合理地阻止写入?

Also, 10M rows is not a large table, by any stretch of the imagination.此外,无论如何,10M 行并不是一张大表。 It probably fits in ram hence will be very quick to alter.它可能适合 ram,因此会很快改变。

This approach is pretty quick这种方法非常快

Query OK, 10000000 rows affected (6 min 0.14 sec)

mysql slow query mysql 慢查询

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM