在线表结构变更
在线表结构变更
对于MySQL而言,DDL操作(比如CREATE/DROP/ALTER等)代价是非常高的,特别是在单表上千万的情况下,加个索引或改个列类型,就有可能堵塞整个表的读写。
方案1
“新表+触发器+迁移数据+rename”,这是业内非常成熟的扩展列的方案,在互联网公司使用广泛。
以user(uid, name, passwd)扩展到user(uid, name, passwd, age, sex)为例
过程如下:
(1)先创建一个扩充字段后的新表user_new(uid, name, passwd, age, sex)
(2)在原表user上创建三个触发器,对原表user进行的所有insert/delete/update操作,都会对新表user_new进行相同的操作
(3)分批将原表user中的数据insert到新表user_new,直至数据迁移完成
(4)删掉触发器,把原表移走(默认是drop掉)
(5)把新表user_new重命名(rename)成原表user
整个过程不需要锁表,可以持续对外提供服务。
注意的地方:
(1)变更过程中最重要的是冲突的处理,:以触发器的新数据为准,这就要求被迁移的表必须有主键(这个要求基本都满足);
(2)变更过程中写操作需要建立触发器,所以如果原表已经有很多触发器,方案就不行;
(3)触发器的建立,会影响原表的性能,所以这个操作建议在流量低峰期进行;
(4)确保磁盘空间充足,因为这个过程需要复制原表以及之后新增的数据。
具体实施,请查阅:pt-online-schema-change,它是Percona-toolkit一员,通过改进原生ddl的方式,达到不锁表在线修改表结构。
方案2
提前预留一些reserved字段,但如果预留过多,会造成空间浪费,预留过少,不一定达得到扩展效果。
方案3
通过增加表的方式扩展列,上游通过service来屏蔽底层的细节。
方案4
从5.6版本开始,MySQL提供了Online DDL功能,可以实现修改表结构的同时,依然允许DML操作(select,insert,update,delete)。
但并不是可以随心所欲地进行DDL,有一些限制:
不允许并发DML的情况
修改列数据类型、删除主键、变更表字符集
可以并发DML的情况
删除并添加主键
添加、删除列,改变列顺序
改变行格式ROW_FORMAT和压缩块大小KEY_BLOCK_SIZE
改变列NULL或NOT NULL
优化表OPTIMIZE TABLE
强制 rebuild 该表
下表是根据官方Summary of Online Status for DDL Operations整理挑选的常用操作。
TODO
参考
pt-online-schema-change使用说明、限制与比较
这才是真正的表扩展方案
Last updated