pt-online-schema-change 最佳实践(转)

pt的详细步骤

Step 1: Create the new table. Step 2: Alter the new, empty table. This should be very quick, or die if the user specified a bad alter statement. Step 3: Create the triggers to capture changes on the original table and apply them to the new table. Step 4: Copy rows. Step 5: Rename tables: orig -> old, new -> orig Step 6: Update foreign key constraints if there are child tables. Step 7: Drop the old table. DROP TABLE IF EXISTS `_xx_old` DROP TRIGGER IF EXISTS `pt_osc_xx_xx_del`; DROP TRIGGER IF EXISTS `pt_osc_xx_xx_upd`; DROP TRIGGER IF EXISTS `pt_osc_xx_xx_ins`; done 

1、经常使用参数解读

1.0 生产环境使用的参数

inception调用pt-online-schema-change,相关参数以下: inception_osc_alter_foreign_keys_method = rebuild_constraints inception_osc_check_alter = on inception_osc_check_interval = 5 inception_osc_check_replication_filters = OFF inception_osc_chunk_size = 1000 inception_osc_chunk_size_limit = 4 inception_osc_chunk_time = 1 inception_osc_critical_thread_connected = 4000 inception_osc_critical_thread_running = 300 inception_osc_drop_new_table = on inception_osc_drop_old_table = on inception_osc_max_lag = 3 inception_osc_max_thread_connected = 2500 inception_osc_max_thread_running = 200 inception_osc_min_table_size = 16 inception_osc_recursion_method = none 以上inception参数对应的pt-online-schema-change的命令参数以下: pt-online-schema-change --alter " xx " --alter-foreign-keys-method=rebuild_constraints --check-alter=yes --check-interval=5 --check-replication-filters=no --chunk-size=1000 --chunk-size-limit=4 --chunk-time=1 --critical-load=thread_connected:4000,thread_running:300 --max-load=thread_connected:2500,thread_running:200 --drop-new-table=yes --drop-old-table=yes --max-lag=3 --recursion-method=none

1.1 基本用法

  • pt-online-schema-change [OPTIONS] DSN
  • pt-online-schema-change --alter "ADD COLUMN c1 INT" D=sakila,t=actor
  • pt-online-schema-change --alter "ENGINE=InnoDB" D=sakila,t=actor

1.2 安全的pt-online-schema-change

默认状况下,pt-online-schema-change 是不会修改表的,除非你显示的指定了 --execute
pt-online-schema-change 有一系列动做来阻住一切不指望的后果发生,包括 自动检测复制,以及如下相关措施javascript

  • 大部分状况下,pt-online-schema-change会拒绝给没有主键和惟一键的表作操做,能够参考 --alter 了解更多信息
  • 若是检测到复制过滤(ignore-db,do-db等),pt-online-schema-change会拒绝操做,能够参考 --[no]check-replication-filters 了解更多信息
  • 若是发现复制严重的厉害,那么会暂停copy数据,能够参考 --max-lag 了解更多的信息
  • 若是发现服务器负载很是高,那么也会暂停或者中止相关操做,能够参考 --max-load and --critical-load 了解更多信息
  • 该工具默认会设置 innodb_lock_wait_timeout=1 和 lock_wait_timeout=60来减小竞争 , 参考 --set-vars 了解更多信息
  • 若是有外键约束,那么禁止改表,出发你指定 --alter-foreign-keys-method.
  • Percona XtraDB Cluster中禁止修改MYISAM的表

1.3 经常使用参数

  • --dry-run and --execute , 这两个是互斥的参数,一个是打印,一个是执行
  • --alter

经过这个选项,就不须要alter table关键字了。 你能够经过逗号来指定多个修改操做。java

* 如下列出--alter中的一些限制,你们谨记和避免

1. 原表必需要有主键或惟一键,由于delete触发器须要用到,不然会报错 2. rename子句,不容许给表重命名 2.1 不能经过删除一列,而后再新增一列的方式来完成对列的重命名操做 3. 新增字段,若是这个字段是NOT NULL,必需要指定default值,不然报错。 你必须指定默认值 4. 若是是DROP FOREIGN KEY constraint_name , 那么必须指定 _ 加上 constraint_name , 而不是 constraint_name。 举例: CONSTRAINT `fk_foo` FOREIGN KEY (`foo_id`) REFERENCES `bar` (`foo_id`) 你必须指定: --alter "DROP FOREIGN KEY _fk_foo" 而不是 --alter "DROP FOREIGN KEY fk_foo". 5. 必须确保数据库高于5.0版本,由于5.0版本转换MYSIAM到InnoDB会出错
  • [no]check-alter

默认yes, 给--alter 作一些检测python

* 列的重命名

在以前的版本 CHANGE COLUMN name new_name 这个操做是会丢失数据的,如今的工具修复了

可是,因为pt代码并非full-blown SQL parser,因此,你应该先 --dry-run and --print , 确认下renamed的列名是否正确,以确保无误 * 删除主键 删除主键是很危险的事情,尽可能不要作这样的动做
  • --alter-foreign-keys-method

咱们的规范不容许有外键,若是有外键,咱们采起其余方式DDLsql

如何把外键引用到新表?须要特殊处理带有外键约束的表,以保证它们能够应用到新表.当重命名表的时候,外键关系会带到重命名后的表上。
该工具备两种方法,能够自动找到子表,并修改约束关系。
    auto: 在rebuild_constraints和drop_swap两种处理方式中选择一个。
    rebuild_constraints:使用 ALTER TABLE语句先删除外键约束,而后再添加.若是子表很大的话,会致使长时间的阻塞。 drop_swap: 执行FOREIGN_KEY_CHECKS=0,禁止外键约束,删除原表,再重命名新表。这种方式很快,也不会产生阻塞,可是有风险: 1, 在删除原表和重命名新表的短期内,表是不存在的,程序会返回错误。 2, 若是重命名表出现错误,也不能回滚了.由于原表已经被删除。 none: 相似"drop_swap"的处理方式,可是它不删除原表,而且外键关系会随着重命名转到老表上面。 
  • --host=xxx --user=xxx --password=xxx
链接实例信息,缩写-h xxx -u xxx -p xxx,密码可使用参数--ask-pass 手动输入。 
  • D=db_name,t=table_name
指定要ddl的数据库名和表名
  • --charset
最好设置为MySQL默认字符集: utf8
  • --check-interval
默认1秒,检测--max-lag 
  • --[no]check-replication-filters

默认yes数据库

若是发现任何服务器有 binlog_ignore_db and replicate_do_db , 那么就报错 
  • --check-slave-lag
指定一个从库的DSN链接地址,若是从库超过--max-lag参数设置的值,就会暂停操做。
  • --[no]swap-tables
默认yes。交换原始表和新表,除非你禁止--[no]drop-old-table。
  • --max-lag
默认1s。
每一个chunk拷贝完成后,会查看全部复制Slave的延迟状况。
要是延迟大于该值,则暂停复制数据,直到全部从的滞后小于这个值,使用Seconds_Behind_Master。
若是有任何从滞后超过此选项的值,则该工具将睡眠--check-interval指定的时间,再检查。 若是从被中止,将会永远等待,直到从开始同步,而且延迟小于该值。 若是指定--check-slave-lag,该工具只检查该服务器的延迟,而不是全部服务器。 
  • --max-load
默认为Threads_running=25。
每一个chunk拷贝完后,会检查SHOW GLOBAL STATUS的内容,检查指标是否超过了指定的阈值。 若是超过,则先暂停。 这里能够用逗号分隔,指定多个条件, 每一个条件格式: status指标=MAX_VALUE 或者 status指标:MAX_VALUE。 若是不指定MAX_VALUE,那么工具会设置其为当前值的120%。 
  • --critical-load
默认为Threads_running=50。
用法基本与--max-load相似,若是不指定MAX_VALUE,那么工具会这只其为当前值的200%。 若是超过指定值,则工具直接退出,而不是暂停。
  • --print
打印SQL语句到标准输出。指定此选项可让你看到该工具所执行的语句,和--dry-run配合最佳。
  • --progress
复制数据的时候打印进度报告,二部分组成:第一部分是百分比,第二部分是时间。
  • --set-vars
设置MySQL变量,多个用逗号分割。
默认该工具设置的是: wait_timeout=10000 innodb_lock_wait_timeout=1 lock_wait_timeout=60
  • --recursion-method
默认是show processlist,发现从的方法,也能够是host,但须要在从上指定report_host,经过show slave hosts来找到,能够指定none来不检查Slave。 METHOD USES =========== ================== processlist SHOW PROCESSLIST hosts SHOW SLAVE HOSTS dsn=DSN DSNs from a table none Do not find slaves 指定none则表示不在意从的延迟。 

--pause-file安全

能够指定文件暂停pt-online-schema-change 

2、使用限制

  • 哪些ddl是不能够作的,作了容易出错
1. 禁止建立惟一索引,会丢失数据,更加不容许添加 --alter-check=no,--check-unique-key-change=no 2. 若是原表没有主键,或者也没有惟一索引,这些表是不容许用pt作DDL的 3. 禁止对外键的表进行pt ddl 4. 禁止对表进行重命名 5. 禁止对列进行重命名,若是必定要作,也必须先print出来检测清楚列名是否正确 6. 新增字段,NOT NULL必需要指定默认值 7. 不容许删除主键
  • 因为pt触发器原理,rowcopy会产业一堆的binlog,因此作以前要检测binlog空间是否够用,也要检测数据空间多一倍表空间是否够用
  • 禁止在业务高峰期进行pt-online-schema-change操做
  • 原表不能有触发器
  • MySQL最好设置为innodb_autoinc_lock_mode=2,不然在高并发的写入状况下,很容易产生所等待以及死锁
  • master的表结构必须跟slave的表结构一致,不容许异构,不然pt-online-schema-change的原理就是会rename,而后slave不一致的表结构会被master覆盖,谨记

3、关于触发器

  • 3.0.2以前的update触发器
REPLACE INTO `lc`.`_hb_new` (`id`, `ts`, `ts2`, `c1`) VALUES (NEW.`id`, NEW.`ts`, NEW.`ts2`, NEW.`c1`)
  • 3.0.2以后的update触发器
BEGIN DELETE IGNORE FROM `lc`.`_hb_new` WHERE !(OLD.`id` <=> NEW.`id`) AND `lc`.`_hb_new`.`id` <=> OLD.`id`; REPLACE INTO `lc`.`_hb_new` (`id`, `ts`, `ts2`) VALUES (NEW.`id`, NEW.`ts`, NEW.`ts2`); END 
  • 原理
update触发器 =SQL转换=> delete ignore + replace into (大于3.0.2版本) =SQL转换=> replace into(低于3.0.2版本,因此这个版本会有问题,若是这时候对老的主键修改,那么修改以前的值不会去掉,从而多了一些异常数据) 举例:t表中有三条数据,第一列id是主键 ------ 1 lc --row1 2 lc --row2 3 lc --row3 ------ pt-online-schema-change的原理大体四个阶段: 1. 建立临时表_t_new 2. 建立触发器 3. 老数据row copy 4. swap table 好了,咱们来举个例子: 1. 建立临时表_t_new 2. 建立触发器 3. 老数据row copy 3.1 拷贝数据row1,row2完毕 3.2 这时候业务有一个update语句, update t set id = 10 where id=1; 3.3 拷贝数据row3 4. swap table 这时候脑补一下原表和新表的示意图, 这时候已经执行到3.1阶段 老表 ------------ 1 lc --row1 2 lc --row2 3 lc --row3 ------------ 新表 ----------- 1 lc 2 lc ----------- 这时候脑补一下原表和新表的示意图, 这时候已经执行到3.3阶段 老表(update t set id = 10 where id=1) ------------ 10 lc --row1 2 lc --row2 3 lc --row3 ------------ 新表(3.0.2以前版本的触发器,没有delete映射,因此最终结果以下,跟老表相比已经不一致了,多了一条数据1,lc) , 触发器 replace into _t_new(id,name) values(10,lc) ----------- 1 lc 2 lc 10 lc 3 lc ----------- 新表(3.0.2以后版本的触发器,有delete映射,因此最终结果以下,于老表的数据一致) , 触发器 delete ignore _t_new where id = 1;replace into _t_new(id,name) values(10,lc); ----------- 2 lc 10 lc 3 lc ----------- 

4、错误处理

遇到错误后,继续补充完整bash

相关文章
相关标签/搜索