我需要更改 MySQL innodb 表中 164M 行的列的长度。这是我要运行的脚本:ALTER TABLE SESSION_DECISION CHANGE COLUMN NAME NAME VARCHAR(255);
当我尝试运行 alter 查询时,数据库混乱了一个小时,没有完成任务。访问系统的用户(需要写入表的用户)被锁定。这是一个实时系统,所以我最终按下 Ctrl-C 键来让用户访问网站。
(这是在半夜——使用次数很少,但我开始紧张)。
我使用的是 MySQL 5.0.77。
关于如何以最少的停机时间更换列,有什么建议吗?
答案1
最好的选择是使用 mysql 复制设置从属数据库。假设您的架构更改是附加的,那么您可以在该副本上发出更新,该副本将在更新期间被阻止。完成后,检查您的从属数据库是否已赶上所有更新,然后声明短暂的停机时间以将您的从属数据库提升为主数据库。
您可以找到有关设置的说明mysql 复制在这里。
答案2
如果您的数据是严格插入(而不是更新)的,您可能会执行以下操作:
- 创建一个具有所需定义的新表。
- 将旧数据复制到新表(确保指定 nolock)
- 关闭对旧表的访问
- 进行从旧到新的增量更新,只是为了捕获复制过程中插入的任何内容。
- 重命名旧表并将新表放到位
- 恢复访问
答案3
当然,这需要很长时间。您应该明白,更改列数据类型会更改底层数据结构,因此必须物理地移动数据,这可能需要很长时间。我不知道您的硬件容量如何,但无论如何,这都将花费一个多小时(想想,一整夜)。
至于减少停机时间的方法,您无法直接做到这一点。我想您没有数据库的备份实例,对吧?
答案4
我听说很多人在提到在虚拟机中运行数据库时会感到畏缩。事实是,这取决于虚拟机。如果您没有虚拟化硬件,那么您就不会遭受他们担心的性能损失。通过 Xen 使用半虚拟化(我听说过 OpenVZ 的好处,但没有用过。)您可以完全按照 Dave Cheney 所说的去做(这是正确的方法),并且只需使用一个硬件。
所使用的工具/概念包括:
- Xen 虚拟化(用于半虚拟化)
- LVM(用于通过快照复制数据)
- 虚拟接口(eth0:1、eth0:2 等),ifup 和 ifdown 来实现...
- 斯托尼特
当然,这不是一份完整的指南,而是一个关于合理技术组合的建议,您可以根据自己的需要进行研究和实施。我的方法更多的是为未来做好准备,而 Dave Cheney 的方法则是处理您(可能)今天所拥有的东西。