很less或没有停机时间修改非常大的MySQL表的列

我需要定期更改mysql 5.1中的表,主要是添加列。 用alter table命令很简单。 但是我的表格现在有多达4000万行,而且它们的增长速度很快…所以这些alter table命令需要几个小时。 在几个月内,他们会花上几天我猜测。

由于我使用亚马逊RDS,我不能有奴隶服务器玩,然后促进主。 所以我的问题是,如果有一种方法可以在最短的停机时间内完成这个任务? 我不介意操作需要几个小时甚至几天,如果用户仍然可以使用数据库当然…他们至less可以阅读而列正在添加? 如果我的应用程序尝试写入会发生什么? 插入或更新? 如果它立即失败,实际上不是那么糟糕,如果它挂起,并导致数据库服务器的问题,这是一个大问题..

这必须是一个相当常见的扩展问题,每个人都需要添加列..什么是通常做生产数据库? 奴隶 – >主迁移?

更新 – 我忘了提及我正在使用innodb存储引擎

我需要定期更改mysql 5.1中的表,主要是添加列。

别。 不完全是。 只是不要。 这是非常罕见的情况下,这是必要的。

假设你的数据真的是规范化的,解决这个问题的正确方法是添加一个与基表有1:1关系的新表(在新表上不是必须的)。

不得不定期添加列通常是未规范化的数据库的指标 – 如果您的模式未规范化,那么这就是您需要解决的问题。

最后,如果你的模式确实是标准化的,而你确实需要继续添加列:

  1. 确保数据库上有时间戳列或正在生成复制日志
  2. 创build表(A)的副本(B)
  3. 将新的列添加到B(这仍将阻止与myisam)
  4. 禁用交易
  5. 将原始表(A)重命名为其他(备份)
  6. 用原始表(A)的名称重新命名新的表(B)
  7. 从复制日志或备份表中的操作开始重放事务
  8. 启用交易。

我最近不得不这样做。 亚马逊build议使用Percona工具包。 我下载了它,并能够运行类似于:

./pt-online-schema-change h=databasenameHostName,D=databasename,t=tablename --recursion-method=none --execute --user username --password password --alter "MODIFY someColumn newDataType" 

而且效果很好。 它告诉你在这个过程中剩下多less时间。

它实际上是用新列创build一个新表,然后复制现有的数据。 此外,它创build一个触发器,以便新数据也被推送到新表。 然后,它会自动重命名表,删除旧表,然后启动并运行新列,并在等待更新时不停机。

symcbean提供了一些可靠的build议 。

要回答你的问题,减轻影响的最简单和最好的方法就是复制多个数据库。 具有适当的故障转移程序的双主站停止活动的复制,这允许在不影响活动的情况下改变不活动。

您可以在单个实时数据库上执行此操作,并通过使用类似于本答复中详述的过程来最大限度地减less影响。 无可否认,这与symcbean描述的相似,但包含了技术细节。 您也可以使用auto_increment字段,而不仅仅是时间戳。

最终,如果您的数据集增长得如此之大,您还需要考虑在OLTP和OLAP数据库之间进行归档。 如果devise得当,交易数据集不需要太大。

从手册: http : //dev.mysql.com/doc/refman/5.1/en/alter-table.html

在大多数情况下,ALTER TABLE会创build原始表的临时副本。 MySQL将这个变更合并到副本中,然后删除原来的表格并重命名新的表格。 在执行ALTER TABLE时,原始表可以被其他会话读取。 对表进行更新和写入操作将停止,直到新表准备就绪,然后自动redirect到新表而不会有任何失败的更新。

所以,阅读将正常工作。 写作将停滞,但之后执行。 如果你想防止这个,你将不得不修改你的软件。

我在类似的情况下,我必须改变我的交易表中,近65GB的1。 我听到2个解决scheme

  1. 使用简单的ALTER,并让它运行(X小时数或天数)
  2. 确保数据库上有时间戳列或正在生成复制日志
    • 创build表(A)的副本(B)
    • 将新的列添加到B(这仍将阻止与myisam)
    • 禁用交易
    • 将原始表(A)重命名为其他(备份)
    • 用原始表(A)的名称重新命名新的表(B)