5. 把Table A 的数据全部复制到Table B, 是不是执行 INSERT INTO B(field1, field2) SELECT field1, field2 FROM A? 当然不是, 这么做不还是锁死了Table A 么, 这里的迁移就是一个需要细分的地方,需要写一个脚本, 让程序每次读取比如5000条数据出来, 插入到Table B里面, 因为Table B 是没有索引的, 所以要当心不要使用多进程来做; 如果是多进程, 要确保插入到B的时候是不会有重复数据的; 如果是1000万的数据,每次5000条, 假设这个操作需要500ms, 那么 2000*200ms = 16 分钟。 这只是一个估值, 具体情况和服务器当时的情况有关, 不好细说。 另外, 我们要记录这个迁移开始的时间点,记为t1;
6. 那么这个时候Table A 的数据是不是都进入了Table B 呢, 应当说差不多大部分都进入了, 但5中说, 这大概需要16分钟, 这么长的时间里, 可能有新的数据进入了, 也有可能已有的数据发生了更新, 所以我们要把Table A 中在t1 之后发生变化的数据查找出来, 然后更新到Table B 中, 我们的做法是:
记录这个操作对应的时间点 t2 BEGIN; DELETE FROM B WHERE updated_time > t1; INSERT INTO B(field1, field2) SELECT field1, field2 FROM A WHERE updated_time >t1; COMMIT;
7. 现在A 和 B 差不多該同步了吧? 差不多了, 但是6 执行完之后, A仍然在写, 子子孙孙无穷尽也 ... , 但这个时候 A 和 B 的差异已经非常非常小了, 所以在下一步,我们在一个transaction 里执行下面的操作:
BEGIN; DELETE FROM B WHERE updated_time > t2; INSERT INTO B(field1, field2) SELECT field1, field2 FROM A WHERE updated_time >t2;
ALTER TABLE A RENAME TO C; ALTER TABLE B RENAME TO A; COMMIT;