在很少或没有停机时间的情况下修改非常大的 mysql 表的列

app*_*ree 19 mysql innodb database database-administration master-slave

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

由于我使用的是 amazon RDS,因此我无法使用从服务器然后升级为主服务器。所以我的问题是是否有办法以最少的停机时间做到这一点?如果用户仍然可以使用数据库,我不介意花费数小时甚至数天的操作......他们至少可以在添加列时阅读吗?如果我的应用尝试写入会发生什么?插入还是更新?如果它立即失败,那实际上并没有那么糟糕,如果它只是挂起并导致数据库服务器出现问题,那就是一个大问题..

这一定是一个相当普遍的缩放问题,每个人都需要添加列.. 通常对生产数据库做什么?从 -> 主迁移?

更新- 我忘了提到我正在使用 innodb 存储引擎

efr*_*dom 11

我最近不得不这样做。亚马逊推荐的是使用 Percona Toolkit。我下载了它并能够运行类似的东西:

./pt-online-schema-change h=databasenameHostName,D=databasename,t=tablename --recursion-method=none --execute --user username --password password --alter "MODIFY someColumn newDataType"
Run Code Online (Sandbox Code Playgroud)

而且效果很好。它会告诉您在此过程中还剩多少时间。

它实际上使用新列创建一个新表,然后复制现有数据。此外,它会创建一个触发器,以便将新数据也推送到新表。然后它会自动重命名表,删除旧表,您就可以使用新列启动并运行,并且在您等待更新时没有停机时间。


sym*_*ean 9

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

别。不完全是。只是不要。这应该是一个非常难得的机会时,这是以往任何时候都需要。

假设您的数据一开始确实是规范化的,那么解决问题的正确方法是添加一个与基表具有 1:1 关系的新表(新表上非强制性)。

必须定期添加列通常表明数据库未规范化 - 如果您的架构未规范化,那么这就是您需要解决的问题。

最后,如果您的架构真的非常规范化并且您真的必须继续添加列,那么:

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

  • 作为一名开发人员,尤其是在初创公司和年轻公司工作的开发人员,我非常同意 symcbean 和 @TomTom。事情变了,产品变了,业务目标变了,数据库结构也需要随之改变。提供良好的 DBA 服务意味着对这些更改说“是”,然后弄清楚如何有效地实施它们。高度规范化的数据库是一个很久以前消亡的概念。它们会导致糟糕的性能和缓慢的开发周期。 (26认同)
  • 换表不常见???也许在大公司中,但在经常发生的敏捷团队中,需求会发生变化...... (4认同)
  • 大约 8 年后 =) 我只是觉得我想说我与 pents90 和 tibo 在一起。symcbean 8 年前所说的完全错误,而且可能当时也是如此。 (4认同)
  • 谢谢你一步一步的方法。修改表格真的不常见吗?我知道我可以使用新列添加另一个表(在需要添加列的情况下),并让它以 1:1 的关系引用原始大表。但是,当它们都应该在 1 个表中时,拥有 15 个非常大的 1:1 表似乎是不正确的......当然,查询性能也会受到影响,更不用说索引问题了。我不是专家,但我的数据库已经很好地规范化了,我需要定期修改似乎很自然。 (2认同)
  • “修改表格真的不常见吗?” - 是的。 (2认同)