mysql的热更工具pt-online-schema-change

mysql5.6前,修改表结构如添加索引、增加列需要锁表(mysql5.5企业版除外),在这期间是不能写入的,由于需要复制原表的数据到中间表,表的数据量越大,等待的时候越长,影响是恶劣的。

我们看一下5.6之前的操作

1. 按照原始表(original_table)的表结构和ddl语句,新建一个不可见的临时表(temporary_table)

2. 在原表上面加上WRITE LOCK,阻塞所有的更新操作(insert、delete、update等操作)

3. 执行insert into tmp_table select * from original_table

4. rename original_table和tmp_table,最后drop original_table

5. 最后释放掉write lock

而使用pt-online-schema-change,则不会锁表,那么它是如何做到不阻塞写入的?

1. 首先创建一个和你要执行的alter操作的表一样的空的表结构。

2. 执行我们赋予的表结构的修改,然后copy原表中的数据到新表里面。

3. 在原表上创建一个触发器在数据copy的过程中,将原表的更新数据的操作全部更新到新的表中来。 这里特别注意一下,如果原表中已经定义了触发器那么工具就不能工作了。(pt-online-schema-change会在原表上创建3个触发器,而一个表上不能同时有2个相同类型的触发器)

4. copy完成之后,用rename table 新表代替原表,默认删除原表。

一样是复制原表数据到中间表,但5.6之前是先锁表,再复制,而pt-online-schema-change工具只是复制,并不锁表,对于后面的修改采用触发器。

我们来看一下例子

Add a column to sakila.actor:

pt-online-schema-change --alter "ADD COLUMN c1 INT" D=sakila,t=actor

使用这个工具会不会风险?官网明确指出是有的。

1.仔细阅读工具文档

2.查阅工具BUG报告

3.在非生产环境下测试

4.做好备份

使用该工具的前提是处理的表需要有主键或则唯一索引。当处理有外键的表时,需要加--alter-foreign-keys-method参数,值可以根据情况设置。当是主从环境,不在乎从的延迟,则需要加--recursion-method=none参数。当需要尽可能的对服务产生小的影响,则需要加上--max-load参数。


查看约束
SELECT * FROM information_schema.`TABLE_CONSTRAINTS`;
查看触发器
SELECT * FROM information_schema.`TRIGGERS`;
如果是工具自己执行不成功的话会自动清理,如果是强制退出的需要手动清理   drop  trigger  Triger_name 
mysql> use hd;
Database changed
mysql> show triggers \G;

mysql5.6后,对online ddl有了很大的改进,修改表结构的同时,允许DDL。

具体的是如何实现的,可以参考这篇文章

http://seanlook.com/2016/05/24/mysql-online-ddl-concept/

不管使用mysql原生的还是pt工具,在修改表结构都需要注意以下事项:(特别是高并发情况下)

0.后台执行(比如screen)

1.有条件的先备份

2.业务低峰执行

3.注意临时表tmpdir空间大小(大于表的大小)

4.磁盘空间

5.是否有在执行大表处理进程

曾经,一台做备份的从库由于tmpdir空间太小出现过Error 'Temporary file write failure。

最后,对于原生online ddl和pt-osc工具来说

1.修改索引、外键、列名时,优先使用online ddl

2.pt-osc会比online ddl慢一点,因为他可以根据负载调整

3.修改表的注释,不管你表多大,直接online ddl

4.表有触发器的时候,不使用pt-osc

PS1:在主从环境下,主库执行alter命令在完成之前是不会进入binlog记录事件

PS2:如何安装pt-osc工具

yum install http://www.percona.com/downloads/percona-release/percona-release-0.0-1.x86_64.rpm
yum install percona-toolkit  -y


PS3:pt-osc的具体使用

原生ddl是这样的

ALTER TABLE `messages` ADD column `group_type` tinyint unsigned NOT NULL DEFAULT 1,ADD column repost_id int unsigned NOT NULL DEFAULT 0,ADD INDEX group_type(message_uid,group_type,id),ADD INDEX repost_id(repost_id)

使用工具

#try-run
pt-online-schema-change --alter "ADD column group_type tinyint unsigned NOT NULL DEFAULT 1,ADD column repost_id int unsigned NOT NULL DEFAULT 0,ADD INDEX group_type(message_uid,group_type,id),ADD INDEX repost_id(repost_id)" --max-lag=0 --recursion-method=processlist --dry-run D=mv,t=messages,h=127.0.0.1,u=root,p="",P=3306

#execute
pt-online-schema-change --alter "ADD column group_type tinyint unsigned NOT NULL DEFAULT 1,ADD column repost_id int unsigned NOT NULL DEFAULT 0,ADD INDEX group_type(message_uid,group_type,id),ADD INDEX repost_id(repost_id)" --max-lag=0 --recursion-method=processlist --execute D=mv,t=messages,h=127.0.0.1,u=root,p="",P=3306

假设你还有从库

recursion-method 发现从的方式
type: array; default: processlist,hosts
--recursion-method=processlist  主从端口相同
--recursion-method=hosts 主从端口不同
--recursion-method=dsn=D=test,t=dsns
--recursion-method=none  不去查找从,即使从有延迟,一般从库延迟会很高 
--max-lag 最大延迟,超过这个就等待  1m 一分钟 如果有没有指定单位,就是秒     --max-lag=1 是比较柔性的修改,修改的比较慢
例子 --max-lag=0 0s 4 4s 如果在超过这个值,就会等待--check-interval时间,直到SLAVE与MASTER 同步
--max-load 最大负载,超过这个就等待 type: Array; default: Threads_running=25
--check-interval 检查间隔,默认是1秒
--check-slave-lag 指定一个从库的DSN连接地址,如果从库超过--max-lag参数设置的值,就会暂停操作
--critical-load Threads_running=200


是暂停还是终止操作这是--max-load和--critical-load的差别。

--nocheck-replication-filters :不检查复制过滤器,建议启用。后面可以用--databases来指定需要检查的数据库。
--no-check-binlog-format : 不检查复制的binlog模式,要是binlog模式是ROW,则会报错。

猜你喜欢

转载自my.oschina.net/longquan/blog/1797329
今日推荐