pt-online-schema-change在线修改表结构

工具简介

pt-osc模仿MySQL内部的改表方式进行改表,但整个改表过程是经过对原始表的拷贝来完成的,即在改表过程当中原始表不会被锁定,并不影响对该表的读写操做。
首先,osc建立与原始表相同的不包含数据的新表并按照需求进行表结构的修改,而后将原始表中的数据按chunk大小逐步拷贝到新表中,当拷贝完成后,会自动同时修改原始表和新表的名字并默认将原始表删除。数据库

pt-online-schema-change原理

一、若是存在外键,根据alter-foreign-keys-method参数的值,检测外键相关的表,作相应设置的处理。
二、建立一个新的表,表结构为修改后的数据表,用于从源数据表向新表中导入数据。
三、建立触发器,用于记录从拷贝数据开始以后,对源数据表继续进行数据修改的操做记录下来,用于数据拷贝结束后,执行这些操做,保证数据不会丢失。
四、拷贝数据,从源数据表中拷贝数据到新表中。
五、修改外键相关的子表,根据修改后的数据,修改外键关联的子表。
六、rename源数据表为old表,把新表rename为源表名,并将old表删除。
七、删除触发器。安全

这个过程当中有两个问题须要注意:
1. 触发器
由于整个过程是在线的,为了将改表过程当中对原始表的更新同时更新到新表上,会建立相应的触发器,每当发生针对原始表的增删改操做,就会触发对新表的相应的操做。因此原始表上不能有其余触发器,即若是原始表上存有触发器,OSC会罢工的。服务器

2. 外键
外键使改表操做变得更加复杂,若是原始表上有外键的话,自动rename原始表和新表的操做就不能顺利进行,必需要在数据拷贝完成后将外键更新到新表上,该工具备两种方法来支持这个操做,具体使用参数(--alter-foreign-keys-method)实现。socket

--alter-foreign-keys-method工具

    外键改表先后必须持续的连接正确的表,当该工具rename原始表并用新表来取代原始表时,外键必须正确更新到新表上,而且原始表中的外键再也不生效性能

有两种方法来实现这个目的,具体参数有四:
(1)auto
  自动决定采用哪一个方法,若是能够就采用rebuild_constraints,若是不能够就采用drop_swap测试

(2)rebuild_constraints
  该方法采用alter table来drop并re-add连接新表的外键。除非相关的子表太大使得alter过程花费时间过长,通常都采用该方法。
这里的花费时间是经过比较子表中的行数和该工具将原始表数据拷贝到新表中的拷贝速率来评估的,若是评估后发现子表中数据可以在少于--chunk-time的时间内alter完成,就会采用该方法。另外,由于在MySQL中alter table比外部拷贝数据的速率快不少,因此拷贝速率是按照--chunk-size-limit来决定的
由于MySQL的限制,外键在改表先后的名字会不同,改表后新表中的外键名前会加一个下划线,一样,会自动的更改外键相应的索引名字ui

(3)drop_swap
  该方法禁止外键检查(FOREIGN_KEY_CHECKS=0),而后在rename新表以前就将原始表drop掉,这个方法更快并且不会被阻塞,可是风险比较大,风险有二:
在drop掉原始表和rename新表之间有一个时间差,在这段时间里这个表是不存在的,这会致使查询报错
若是rename新表时发生了错误,那问题就大了,由于原始表已经被drop掉了.net

(4)none
  这个方法相似没有“swap”的drop_swap,原始表中的全部外键都会被指定到一个不存在的表上blog

参数列表

--user:  -u,链接的用户名     

--password:  -p,链接的密码  

--database:  -D,链接的数据库  

--port:  -P,链接数据库的端口  

--host:  -h,链接的主机地址  

--socket:  -S,链接的套接字文件  

--ask-pass  隐式输入链接MySQL的密码  

--charset  指定修改的字符集  

--defaults-file  -F,读取配置文件  

--alter:  

结构变动语句,不须要alter table关键字。能够指定多个更改,用逗号分隔。以下场景,须要注意:  

    不能用RENAME来重命名表。          

    列不能经过先删除,再添加的方式进行重命名,不会将数据拷贝到新列。  

    若是加入的列非空并且没有默认值,则工具会失败。即其不会为你设置一个默认值,必须显示指定。  

    删除外键(drop foreign key constrain_name)时,须要指定名称_constraint_name,而不是原始的constraint_name。  

    如:CONSTRAINT `fk_foo` FOREIGN KEY (`foo_id`) REFERENCES `bar` (`foo_id`),须要指定:--alter "DROP FOREIGN KEY _fk_foo"  

--alter-foreign-keys-method  

如何把外键引用到新表?须要特殊处理带有外键约束的表,以保证它们能够应用到新表.当重命名表的时候,外键关系会带到重命名后的表上。  

该工具备两种方法,能够自动找到子表,并修改约束关系。  

    auto: 在rebuild_constraints和drop_swap两种处理方式中选择一个。  

    rebuild_constraints:使用 ALTER TABLE语句先删除外键约束,而后再添加.若是子表很大的话,会致使长时间的阻塞。  

    drop_swap: 执行FOREIGN_KEY_CHECKS=0,禁止外键约束,删除原表,再重命名新表。这种方式很快,也不会产生阻塞,可是有风险:  

    1, 在删除原表和重命名新表的短期内,表是不存在的,程序会返回错误。  

    2, 若是重命名表出现错误,也不能回滚了.由于原表已经被删除。  

    none: 相似"drop_swap"的处理方式,可是它不删除原表,而且外键关系会随着重命名转到老表上面。  

--[no]check-alter  

  默认yes,语法解析。配合--dry-run 和 --print 一块儿运行,来检查是否有问题(change column,drop primary key)。     

--max-lag  

  默认1s。每一个chunk拷贝完成后,会查看全部复制Slave的延迟状况。要是延迟大于该值,则暂停复制数据,直到全部从的滞后小于这个值,使用Seconds_Behind_Master。若是有任何从滞后超过此选项的值,则该工具将睡眠--check-interval指定的时间,再检查。若是从被中止,将会永远等待,直到从开始同步,而且延迟小于该值。若是指定--check-slave-lag,该工具只检查该服务器的延迟,而不是全部服务器。     

--check-slave-lag  

  指定一个从库的DSN链接地址,若是从库超过--max-lag参数设置的值,就会暂停操做。   

--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则表示不在意从的延迟。  

 

--check-interval   默认是1。--max-lag检查的睡眠时间。   

--[no]check-plan   默认yes。检查查询执行计划的安全性。   

--[no]check-replication-filters   

  默认yes。若是工具检测到服务器选项中有任何复制相关的筛选,如指定binlog_ignore_db和replicate_do_db此类。发现有这样的筛选,工具会报错且退出。由于若是更新的表Master上存在,而Slave上不存在,会致使复制的失败。使用–no-check-replication-filters选项来禁用该检查。   

--[no]swap-tables   默认yes。交换原始表和新表,除非你禁止--[no]drop-old-table。   

--[no]drop-triggers   

  默认yes,删除原表上的触发器。 --no-drop-triggers 会强制开启 --no-drop-old-table 即:不删除触发器就会强制不删除原表。   

--new-table-name   复制建立新表的名称,默认%T_new。   

--[no]drop-new-table   默认yes。删除新表,若是复制组织表失败。   

--[no]drop-old-table   默认yes。复制数据完成重命名以后,删除原表。若是有错误则会保留原表。   

--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%。若是超过指定值,则工具直接退出,而不是暂停。   

--default-engine   

  默认状况下,新的表与原始表是相同的存储引擎,因此若是原来的表使用InnoDB的,那么新表将使用InnoDB的。在涉及复制某些状况下,极可能主从的存储引擎不同。使用该选项会默认使用默认的存储引擎。      

--set-vars   

  设置MySQL变量,多个用逗号分割。默认该工具设置的是: wait_timeout=10000 innodb_lock_wait_timeout=1 lock_wait_timeout=60      

--chunk-size-limit  

  当须要复制的块远大于设置的chunk-size大小,就不复制.默认值是4.0,一个没有主键或惟一索引的表,块大小就是不肯定的。     

--chunk-time  

  在chunk-time执行的时间内,动态调整chunk-size的大小,以适应服务器性能的变化,该参数设置为0,或者指定chunk-size,均可以禁止动态调整。     

--chunk-size  

  指定块的大小,默认是1000行,能够添加k,M,G后缀.这个块的大小要尽可能与--chunk-time匹配,若是明确指定这个选项,那么每一个块就会指定行数的大小.     

--[no]check-plan  

  默认yes。为了安全,检查查询的执行计划.默认状况下,这个工具在执行查询以前会先EXPLAIN,以获取一次少许的数据,若是是很差的EXPLAIN,那么会获取一次大量的数据,这个工具会屡次执行EXPALIN,若是EXPLAIN不一样的结果,那么就会认为这个查询是不安全的。      

--statistics  打印出内部事件的数目,能够看到复制数据插入的数目。     

--dry-run  建立和修改新表,但不会建立触发器、复制数据、和替换原表。并不真正执行,能够看到生成的执行语句,了解其执行步骤与细节。--dry-run与--execute必须指定一个,两者相互排斥。和--print配合最佳。  

--execute  肯定修改表,则指定该参数。真正执行。--dry-run与--execute必须指定一个,两者相互排斥。     

--print  打印SQL语句到标准输出。指定此选项可让你看到该工具所执行的语句,和--dry-run配合最佳。    

--progress  复制数据的时候打印进度报告,二部分组成:第一部分是百分比,第二部分是时间。    

--quiet  -q,不把信息标准输出。

测试用例

添加字段

pt-online-schema-change --user=root --password=123456 --host=192.168.200.25  --alter "ADD COLUMN content text" D=aaa,t=tmp_test --no-check-replication-filters --alter-foreign-keys-method=auto --recursion-method=none --print --execute

删除字段

pt-online-schema-change --user=root --password=123456 --host=192.168.200.25  --alter "DROP COLUMN content " D=aaa,t=tmp_test --no-check-replication-filters --alter-foreign-keys-method=auto --recursion-method=none --quiet --execute

修改字段

pt-online-schema-change --user=root --password=123456 --host=192.168.200.25  --alter "MODIFY COLUMN age TINYINT NOT NULL DEFAULT 0" D=aaa,t=tmp_test --no-check-replication-filters --alter-foreign-keys-method=auto --recursion-method=none --quiet --execute

字段更名

pt-online-schema-change --user=root --password=123456 --host=192.168.200.25  --alter "CHANGE COLUMN age address varchar(30)" D=aaa,t=tmp_test --no-check-alter --no-check-replication-filters --alter-foreign-keys-method=auto --recursion-method=none --quiet --execute

增长索引

pt-online-schema-change --user=root --password=123456 --host=192.168.200.25  --alter "ADD INDEX idx_address(address)" D=aaa,t=tmp_test --no-check-alter --no-check-replication-filters --alter-foreign-keys-method=auto --recursion-method=none --print --execute

删除索引

pt-online-schema-change --user=root --password=123456 --host=192.168.200.25  --alter "DROP INDEX idx_address" D=aaa,t=tmp_test --no-check-alter --no-check-replication-filters --alter-foreign-keys-method=auto --recursion-method=none --print --execute 

 

参考:https://blog.csdn.net/lovelichao12/article/details/73549939

相关文章
相关标签/搜索