pt-online-schema-change
        不锁表的情况下,修改表结构.

    该工具执行的基本流程如下:

   判断各种参数

    如果表有外键,除非使用 --alter-foreign-keys-method 指定特定的值,否则工具不予执行。

    根据原表"t",创建一个名称为"_t_new"的新表
    执行ALTER TABLE语句修改新表"_t_new"
    创建3个触发器,名称格式为pt_osc_库名_表名_操作类型,比如

  CREATE TRIGGER `pt_osc_dba_t_del` AFTER DELETE ON `dba`.`t` FOR EACH ROW DELETE IGNORE FROM `dba`.`_t_new` WHERE `dba`.`_t_new`.`id` <=> OLD.`id`
    CREATE TRIGGER `pt_osc_dba_t_upd` AFTER UPDATE ON `dba`.`t` FOR EACH ROW REPLACE INTO `dba`.`_t_new` (`id`, `a`, `b`, `c1`) VALUES (NEW.`id`, NEW.`a`, NEW.`b`, NEW.`c1`)
    CREATE TRIGGER `pt_osc_dba_t_ins` AFTER INSERT ON `dba`.`t` FOR EACH ROW REPLACE INTO `dba`.`_t_new` (`id`, `a`, `b`, `c1`) VALUES (NEW.`id`, NEW.`a`, NEW.`b`, NEW.`c1`)

    开始复制数据,比如

    INSERT LOW_PRIORITY IGNORE INTO `dba`.`_t_new` (`id`, `a`, `b`, `c1`) SELECT `id`, `a`, `b`, `c1` FROM `dba`.`t` LOCK IN SHARE MODE /*pt-online-schema-change 28014 copy table*/

    复制完成后,交互原表和新表,执行RENAME命令,如 RENAME TABLE t to _t_old, _t_new to t;
    删除老表,_t_old
    删除触发器
    修改完成

OPTIONS

参数 --dry-run 和 --execute 是互斥的.
该工具接收额外的命名行参数.更多信息请参考”SYNOPSIS"和usage部分.
   

 --alter
    type: string
    结构修改,不带ALTER TABLE关键字.你可以执行多个表的修改操作,在它们之间用逗号分割.关于ALTER TABLE语法,请参考MySQL手册.
    该参数有以下局限性,如果被触发,会导致这个工具执行失败:
        不能指定rename语句.
        不能用删除列添加新列的方法重命名.该工具将不能复制原表中此列的数据到新列.
        如果你添加一个没有默认值新列并且属性设置为NOT NULL,该工具将不能执行,它不会给你指定一个默认值.
        删除外键约束,需要指定一个外键的名字,但是,这个名字并不是外键的名字,而是一个区别于外键的名字.这是MySQL的限制.在创建新表的时候, pt-online-schema-change会创建一个以下划线开头的外键.比如
        CONSTRAINT `fk_foo` FOREIGN KEY (`foo_id`) REFERENCES `bar` (`foo_id`)
        然后,必须这样指定
        --alter "DROP FOREIGN KEY _fk_foo" 
        在MySQL 5.0版本操作可能会有问题.
    --alter-foreign-keys-method
    如何把外键引用到新表?需要特殊处理带有外键约束的表,以保证它们可以应用到新表.当重命名表的时候,外键关系会带到重命名后的表上.
    该工具有两种方法,可以自动找到子表,并修改约束关系.
        auto, 在rebuild_constraints和drop_swap两种处理方式中选择一个.
        rebuild_constraints, 使用 ALTER TABLE语句先删除外键约束,然后再添加.如果子表很大的话,会导致长时间的阻塞.
        drop_swap, 执行FOREIGN_KEY_CHECKS=0,禁止外键约束,删除原表,再重命名新表.
        这种方式很快,也不会产生阻塞,但是有风险:
        1, 在删除原表和重命名新表的短时间内,表是不存在的,程序会返回错误.
        2, 如果重命名表出现错误,也不能回滚了.因为原表已经被删除.
        none, 类似"drop_swap"的处理方式,但是它不删除原表,并且外键关系会随着重命名转到老表上面.使用SHOW ENGINE INNODB STATUS;命令会发现如下错误信息
        Trying to add to index `idx_fk_staff_id` tuple:
        DATA TUPLE: 2 fields;
        0: len 1; hex 05; asc  ;;
        1: len 4; hex 80000001; asc     ;;
        But the parent table `sakila`.`staff_old`
        or its .ibd file does not currently exist!
    --ask-pass
    连接MySQL时,提示输入密码
    --charset
    设置字符集,相当于用客户端执行"SET NAMES UTF8"命令
    --[no]check-alter
    解析并检查alter指定的命令:
        在以前的版本,使用CHANGE COLUMN命令会导致数据丢失,现在的版本虽然改进,但是在执行前,还应该使用 --dry-run 和 --print 查看一下详细的操作情况.
        DROP PRIMARY KEY, 执行该命令的话,会发出警告.
    --check-interval
    检查间隔,默认是1秒.请看--max-lag参数.
    --[no]check-plan
    为了安全,检查查询的执行计划.默认情况下,这个工具在执行查询之前会先EXPLAIN,以获取一次少量的数据,如果是不好的EXPLAIN,那么会获取一次大量的数据.
    这个工具会多次执行EXPALIN,如果EXPLAIN不同的结果,那么就会认为这个查询是不安全的.
    --[no]check-replication-filters
    检查MySQL的复制过滤器,如果存在就报错退出.
    如:binlog_ignore_db 和 replicate_do_db
    --check-slave-lag
    指定一个从库的DSN连接地址,如果从库超过--max-lag参数设置的值,就会暂停操作.
    --chunk-index
    为chunk指定一个索引(使用FORCE INDEX语法).
    默认情况下,工具会自动选择一个合适的索引.如果指定的索引不存在,该工具会自动选择一个合适的.
    --chunk-index-columns
    选择使用具有n列的索引,多用于复合索引.
    --chunk-size
    指定块的大小,默认是1000行,可以添加k,M,G后缀.这个块的大小要尽量与--chunk-time匹配.
    如果明确指定这个选项,那么每个块就会指定行数的大小.
    --chunk-size-limit
    当需要复制的块远大于设置的chunk-size大小,就不复制.默认值是4.0
    一个没有主键或唯一索引的表,块大小就是不确定的.
    --chunk-time
    在chunk-time执行的时间内,动态调整chunk-size的大小,以适应服务器性能的变化.
    该参数设置为0,或者指定chunk-size,都可以禁止动态调整.
    --config
    执行配置文件,必须在命令行的第一个参数位置.
    --critical-load


测试例子:

1)添加一列,并不真正执行

pt-online-schema-change –alter “add column c1 int” D=mydb,t=mytable –dry-run

2)更新存储引擎为InnoDB,不删除原表

pt-online-schema-change –alter “ENGINE=InnoDB” –no-drop-old-table –print –statistics –execute D=mydb,t=mytable –execute

通过OSC实现slave和master数据差异时候的恢复.有人说,这个是pt-table-sync该干的事情.但是在表数据差异较大的时候,使用OSC可能效率更好,而且更加简单可靠.
OSC如何实现master到slave的数据差异恢复的?
由于OSC的原理是新建表和使用触发器.然后把原表的数据insert into select from的方式导入新表.如果这个时候,我们把binlog改成row格式.那么insert into记录的肯定是源表的数据了.触发器在row格式的时候,也是在日志中记录的源表数据.也就是说,通过OSC可以逻辑的,无阻塞的把源表的数据同步 到所有slave.

pt-online-schema-change -set-vars 'binlog_format=ROW' -alter 'engine=INNODB' D=mydb,t=mytest,h=localhost –execute

如果你本来就工作在row格式下,那么–set-vars ‘binlog_format=ROW’就可以不设置了.

3)复制环境下,忽略日志筛选和Slave复制延迟,删除表字段

pt-online-schema-change–no-check-replication-filters –recursion-method=none –alter “drop company_type,drop channel_code” h=192.168.10.14,P=3370,u=user1,p=pass1,D=db1,t=table1 –print –statistics–execute

4)更新被子表引用到的父表

pt-online-schema-change -alter “add newcol int” h=192.168.10.14,P=3370,u=user1,p=pass1,D=db1,t=table1 -alter-foreign-keys-method auto -print -statistics -execute


5)在我们的双主复制环境中,设定了忽略mysql库的复制,不是很在乎复制的延迟,有时有外键影响,希望尽量保留原表数据,必要时自行删除。

pt-online-schema-change -no-check-replication-filters -recursion-method=none -alter “drop 
newcol” h=192.168.10.14,P=3370,u=user1,p=pass1,D=db1,t=table1 -alter-foreign-keys-method auto -no-drop-old-table -print -statistics -execute

6)修改表结构的一个字段大小

pt-online-schema-change --user=root  --host=127.0.0.1 --password=123456 --alter "CHANGE hardware_num hardware_num VARCHAR(64) NOT NULL DEFAULT ''"  --set-vars   wait_timeout=10000,innodb_lock_wait_timeout=10,lock_wait_timeout=120  --max-load=Threads_running=16  --critical-load=Threads_running=50  D=db1,t=table1 --chunk-size 2000 --nodrop-old-table --execute