pt-online-schema-change可以在不阻塞读写的情况下在线整理表结构、收集碎片、给大表加字段和索引,并且可以实时查看执行进度。
原理
pt-online-schema-change在工作过程时,首先会创建一张要修改的表的空表,在空表上执行alter语句。然后从原始表中copy数据行导入新表。拷贝完成后,会将原表移走,用新表代替原表,最后删除原始表。
数据是以一定的块大小从原表拷贝到临时表,在数据拷贝前,会在原表上创建delete触发器、update触发器、insert触发器,拷贝过程中在原表上进行的写操作都会通过触发器更新到临时表。
当完成数据拷贝过程后,会用rename table的方式交换原表和临时表的表名。
最后会删除触发器以及原表。
PT-OSC工具的限制
参数详解
使用示例
1. 添加新列
pt-online-schema-change --user=root --password=root --alter "add column score int(3)" D=test,t=tuser --print --execute
2. 修改字段类型
pt-online-schema-change --user=root --password=root --alter "modify score varchar(10) DEFAULT NULL" D=test,t=tuser --print --execute --no-check-alter
3. 删除索引
pt-online-schema-change --user=root --password=root --alter "drop index name_age" D=test,t=tuser --print --execute
4. 增加索引
pt-online-schema-change --user=root --password=root --alter "add index idx_id_card(id_card)" D=test,t=tuser --print --execute
5. 修改存储引擎、碎片整理
pt-online-schema-change --user=root --password=root --alter "engine=innodb" D=test,t=tuser –execute
一些思考
在之前研究pt-osc的时候,思考过这么一个问题,我们知道在执行过程中会在原表上建立触发器,当有业务update原表时,触发器会在临时表上同样进行update,那如果此时原表上要update的数据还没有copy到临时表该怎么办呢?
后来了解到,在原表update时,临时表上采用的是replace into的方式调整数据,replace into和insert功能不太一样,replace into会先尝试插入数据到表中,如果发现表中已经有此行数据,则先删除再插入,否则直接插入。所以这也要求每张表必须有主键或者唯一索引,不然有可能会出现数据重复的情况。