2011-05-31 59 views
2

我们使用InnoDB引擎在MySql中存储了一个非常大的(10百万以上)行表。列'x'被定义为'smallint(5)unsigned not null'。InnoDB上的MySql数值类型迁移

自从几年前的原始设计以来,需求已经发生变化,而'x'列需要存储最小数据类型大小'int unsigned not null'。

我们被允许“短暂”停机以部署应用程序(少于5分钟),因此如果数据库表需要暂时以任何方式暂时不可用(例如,全表锁)。如果更改可以“在线”完成,那么我们可能会接受较长时间的性能下降。

有没有人有过在非常大的表上更改MySql/InnoDB中的列类型的经验?如果是这样,它是否行得通,大致需要多长时间(我意识到这是硬件依赖的,我只是想了解我们在时间窗口中要求做的事情是否甚至有可能)?

由于提前,

+0

多久,当你在测试实验室应用到一个同样大小的桌子上生产高档五金没ALTER TABLE走? – MarkR 2011-05-31 19:18:22

+0

@MarkR - 正在进行中,但可能需要一段时间才能将环境设置为脱离我的团队控制。因此,试图在此期间获得可行性的想法... – Scruffers 2011-05-31 19:48:22

回答

1

继承人我用

,你有旧列配方,一个

  1. 创建一个新的B柱
  2. 创建触发器来更新b在更新/插入上
  3. 更新b = a
  4. 删除所有fkey关系引用
  5. 创建对于B FKEY关系
  6. 更新代码,而不是使用B列(部署)
  7. 滴在列
  8. 删除列触发

重复所有步骤,如果你必须改变列名返回。

+0

谢谢!这是一个非常有趣的想法 - 我需要考虑它,但它可能只适用于我们... – Scruffers 2011-05-31 19:46:21

0

您可以通过创建一个新表作为原始布局的克隆来联机。

CREATE TABLE newtable LIKE oldtable; 

其次,改变你的新表的字段,以满足新规范

ALTER TABLE newtable ... ; 

一旦这样做了,复制的数据。

INSERT INTO newtable SELECT * FROM oldtable; 

最后,用你几分钟的停机时间,以你的旧表重命名为别的东西,然后给你的新表旧表的名称。

当然,您需要有足够的存储空间来存放两张表格。此外,在复制操作期间,您可能希望在执行复制时禁用新表上的索引以减少服务器上的压力。

一旦您确信旧表中的所有数据都已被复制到新的数据库中,您可以最终完全删除旧表。

编辑:

其实,更好的方法可能是刚加入新列到符合您要更新列的新要求,现有的表,旧列的值复制到新的列,删除旧列并将新列重命名为旧列的名称。它肯定会降低您的存储需求。另外,如果您有任何取决于相关列的FK约束,您需要在启动之前将其删除,并在完成后将其恢复到新列。

+0

以及在复制操作过程中添加到表中的数据/修改了哪些数据? – fvu 2011-05-31 19:08:17

+0

谢谢,但是我分享了@fvu的关注,因为这张表是由每次交易触及应用服务器(即每分钟多次)更新的。 – Scruffers 2011-05-31 19:44:18

+0

好吧,这是一个很好的观点,没有想到这一点。我想你可以实现一个触发器来保持两个列/表同步,直到你准备好切换。 – GordonM 2011-06-01 05:34:46

0

你现在有什么样的高可用性解决方案?

我问,因为5分钟是不够的停机时间,以允许重新启动正常的任务,如操作系统更新。

因此,您必须拥有某种高可用性解决方案,以允许这些常规(我假设您的操作团队会不时应用补丁)更新。

应该可以使用这样的系统来做到这一点。但是,ALTER TABLE允许表在整个运行过程中始终保持读取操作的可用状态,并且只有块在最后短时间读取(大多数系统上的读取时间少于5分钟)。

所以问,你什么时候可以合理地阻止写入?

另外,10M行不是一个大的表,通过任何想象力。它可能适合公羊,因此将很快改变。

+0

对于高可用性:负载均衡器后面的两个无状态应用服务器意味着它们可以独立取消用于操作系统补丁等。但是,两个应用服务器共享相同的数据库状态,这是我们所关注的状态,因为我们无法阻止写入这个表在所有应用服务器启动时,如果它们停止运行,那就是5分钟(ish)窗口进入的地方。 – Scruffers 2011-05-31 19:40:15

+0

关于规模:很有用10M不是“大”,我们正在进行一些性能测试这很有趣,看看这是否是一个非问题... – Scruffers 2011-05-31 19:42:44

0

这种做法是相当快

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

mysql slow query