我很想知道人们在 MySQL 中对非常大的表执行更改时使用的策略和方法。大可以是任何行数或大小,都会对更改产生影响。为了方便交流,我们假设有 200 多万行,任何更改都会对正常的应用程序性能产生影响。
我看到的两个主要策略是在从属服务器上执行更改,然后在完成后将其提升为主服务器,或者创建已完成预期更改的表的副本,然后复制并捕获数据并进行重命名以在删除旧数据之前将它们换出。
我理想情况下正在寻找一种实现后者的方法。我在这里最担心的是表上的触发器被更改,当然还要确保在交换两个表之前,这两个表中的数据保持同步。我认为,通过在流程的关键点使用 read_only 变量,可以在一定程度上减轻出现错误或丢失数据的可能性,以确保在摆弄触发器时以及在您获取所有数据之后数据不会发生变化。我知道这会对使用数据库的应用程序产生影响,但这比冒着数据损坏的风险要好。
我一直在研究实现此目的的实用工具和策略,目前已有多种方案。其中一个值得注意的方案是 Facebook 将其用作其在线更改的基础。:openark 套件文档。该过程详细说明如下:关于在线模式变更的想法和观点
您对这两种方法有什么经验?您遇到了哪些陷阱和问题?您更喜欢/建议哪种方法?为什么?
Percona/Maatkit 也有自己的:pt-在线-架构更改
答案1
我已经使用触发器方法对超过 1 亿行的表进行了在线模式更改,效果非常好。
- 创建具有所需结构的新表。
向旧表添加触发器以将插入的数据复制到新表。它看起来像:
DELIMITER | CREATE TRIGGER original_to_new AFTER INSERT ON original_table FOR EACH ROW BEGIN INSERT INTO new_table SET col1 = NEW.col1, col2 = NEW.col2... END; | DELIMITER ;
记下第一个使用触发器移动到新表的自动增量 ID。
- 将数据从旧表复制到新表,直到达到步骤 3 中捕获的 ID。
- 交换表名。
RENAME original_table TO original_table_backup, new_table TO original_table
- 删除旧表
答案2
Continuent 公司将这一功能添加到了他们的 Tungsten Enterprise 产品中。例如:https://s3.amazonaws.com/releases.continuent.com/doc/tungsten-1.3.3/html/Tungsten-Concepts-And-Administration-Guide/content/ch03s19.html