很久没有写博客了,今天发表一篇吧:)html
一般的在线进行表字段的增减都会形成表所,若是表较小还能接受,若是过大则这个锁持续的时间会让人比较烦恼,对业务持续性影响较大。mysql
Percona 提供了一款关于MySQL管理的工具集很强大,包括了在线DDL工具 pt-online-schema-changesql
安装就不介绍了,自行百度吧网络
下面的原理介绍摘自网络http://www.it165.net/pro/html/201312/8928.html,写的比较清晰,就不重复造轮子了。app
+++++++++++++++++++++ide
模仿MySQL的alter,但不一样的是在alter操做更改表结构的时候不用锁定表,也就是说执行alter的时候不会阻塞写和读取操做,客户端能够继续都和修改数据。注意执行这个工具的时候必须作好备份,操做以前最好详细读一下官方文档。工具
一、若是存在外键,根据alter-foreign-keys-method参数的值,检测外键相关的表,作相应设置的处理。没有使用 --alter-foreign-keys-method 指定特定的值,该工具不予执行测试
二、建立一个新的表,表结构为修改后的数据表,用于从源数据表向新表中导入数据。ui
三、建立触发器,用于记录从拷贝数据开始以后,对源数据表继续进行数据修改的操做记录下来,用于数据拷贝结束后,执行这些操做,保证数据不会丢失。若是表中已经定义了触发器这个工具就不能工做了。this
四、拷贝数据,从源数据表中拷贝数据到新表中。
五、修改外键相关的子表,根据修改后的数据,修改外键关联的子表。
六、rename源数据表为old表,把新表rename为源表名,并将old表删除。
七、删除触发器。
+++++++++++++++++++
相关的参数请 --help
1. 进行--dry-run测试
[root@master ~]# pt-online-schema-change --user=root --password=root --host=localhost --alter='ENGINE=Innodb' D=baby,t=baby_account --dry-run
Operation, tries, wait:
analyze_table, 10, 1
copy_rows, 10, 0.25
create_triggers, 10, 1
drop_triggers, 10, 1
swap_tables, 10, 1
update_foreign_keys, 10, 1
Child tables:
`baby`.`baby_account_billing_contract` (approx. 21 rows)
`baby`.`baby_account_tactics` (approx. 13308 rows)
`baby`.`baby_account_tactics_bak` (approx. 1672 rows)
`baby`.`baby_billing` (approx. 11856 rows)
`baby`.`baby_billing_apply` (approx. 128 rows)
`baby`.`baby_order_bak_haochongpei` (approx. 1 rows)
You did not specify --alter-foreign-keys-method, but there are foreign keys that reference the table. Please read the tool's documentation carefully.
##表有主键,对主键的处理方式须要明确指出
--alter-foreign-keys-method 说明:
如何把外键引用到新表?须要特殊处理带有外键约束的表,以保证它们能够应用到新表.当重命名表的时候,外键关系会带到重命名后的表上。
该工具备两种方法,能够自动找到子表,并修改约束关系。
auto 在rebuild_constraints和drop_swap两种处理方式中选择一个
rebuild_constraints使用 ALTER TABLE语句先删除外键约束,而后再添加.若是子表很大的话,会致使长时间的阻塞。
drop_swap 执行FOREIGN_KEY_CHECKS=0,禁止外键约束,删除原表,再重命名新表。这种方式很快,也不会产生阻塞,可是有风险:
1, 在删除原表和重命名新表的短期内,表是不存在的,程序会返回错误。
2, 若是重命名表出现错误,也不能回滚了.由于原表已经被删除。
none 相似"drop_swap"的处理方式,可是它不删除原表,而且外键关系会随着重命名转到老表上面。
我这里指定的是auto自动选择,能够看到下文的提示
[root@master ~]# pt-online-schema-change --user=root --password=root --host=localhost --alter='ENGINE=Innodb' D=baby,t=baby_account --alter-foreign-keys-method=auto --dry-run
Operation, tries, wait:
analyze_table, 10, 1
copy_rows, 10, 0.25
create_triggers, 10, 1
drop_triggers, 10, 1
swap_tables, 10, 1
update_foreign_keys, 10, 1
Child tables:
`baby`.`baby_account_billing_contract` (approx. 21 rows)
`baby`.`baby_account_tactics` (approx. 13308 rows)
`baby`.`baby_account_tactics_bak` (approx. 1672 rows)
`baby`.`baby_billing` (approx. 11856 rows)
`baby`.`baby_billing_apply` (approx. 128 rows)
`baby`.`baby_order_bak_haochongpei` (approx. 1 rows)
Will automatically choose the method to update foreign keys.
Starting a dry run. `baby`.`baby_account` will not be altered. Specify --execute instead of --dry-run to alter the table.
Creating new table...
Created new table baby._baby_account_new OK.
Altering new table...
Altered `baby`.`_baby_account_new` OK.
Not creating triggers because this is a dry run.
Not copying rows because this is a dry run.
Not determining the method to update foreign keys because this is a dry run.
Not swapping tables because this is a dry run.
Not updating foreign key constraints because this is a dry run.
Not dropping old table because this is a dry run.
Not dropping triggers because this is a dry run.
2016-08-29T14:31:59 Dropping new table...
2016-08-29T14:31:59 Dropped new table OK.
Dry run complete. `baby`.`baby_account` was not altered.
执行操做,看到报错,由于我这环境是主从复制的环境,因此--check-replication-filters参数须要明确指出
[root@master ~]# pt-online-schema-change --user=root --password=root --host=localhost --alter='ENGINE=Innodb' D=baby,t=baby_account --alter-foreign-keys-method=auto --execute
Found 2 slaves:
client.wboy.com
client1.wboy.com
Will check slave lag on:
client.wboy.com
client1.wboy.com
Replication filters are set on these hosts:
client.wboy.com
binlog_ignore_db = mysql,test,information_schema,performance_schema
client1.wboy.com
binlog_ignore_db = mysql,test,information_schema,performance_schema
Please read the --check-replication-filters documentation to learn how to solve this problem. at /usr/local/bin/pt-online-schema-change line 8493.
[root@master ~]# pt-online-schema-change --user=root --password=root --host=localhost --alter='ENGINE=Innodb' D=baby,t=baby_account --alter-foreign-keys-method=auto --no-check-replication-filters --execute
Found 2 slaves:
client.wboy.com
client1.wboy.com
Will check slave lag on:
client.wboy.com
client1.wboy.com
Operation, tries, wait:
analyze_table, 10, 1
copy_rows, 10, 0.25
create_triggers, 10, 1
drop_triggers, 10, 1
swap_tables, 10, 1
update_foreign_keys, 10, 1
Child tables:
`baby`.`baby_account_billing_contract` (approx. 21 rows)
`baby`.`baby_account_tactics` (approx. 13308 rows)
`baby`.`baby_account_tactics_bak` (approx. 1672 rows)
`baby`.`baby_billing` (approx. 11856 rows)
`baby`.`baby_billing_apply` (approx. 128 rows)
`baby`.`baby_order_bak_haochongpei` (approx. 1 rows)
Will automatically choose the method to update foreign keys.
Altering `baby`.`baby_account`...
Creating new table...
Created new table baby._baby_account_new OK.
Waiting forever for new table `baby`.`_baby_account_new` to replicate to client1.wboy.com...
Waiting for client1.wboy.com: 0% 00:00 remain
Waiting for client1.wboy.com: 0% 00:00 remain
Altering new table...
Altered `baby`.`_baby_account_new` OK.
2016-08-29T14:54:50 Creating triggers...
2016-08-29T14:54:50 Created triggers OK.
2016-08-29T14:54:50 Copying approximately 20189 rows...
Replica lag is 32 seconds on client1.wboy.com. Waiting.
Replica lag is 60 seconds on client1.wboy.com. Waiting.
Copying `baby`.`baby_account`: 13% 06:43 remain
Replica lag is 32 seconds on client1.wboy.com. Waiting.
Replica lag is 60 seconds on client1.wboy.com. Waiting.
Copying `baby`.`baby_account`: 58% 01:33 remain
Replica lag is 31 seconds on client1.wboy.com. Waiting.
Replica lag is 59 seconds on client1.wboy.com. Waiting.
Copying `baby`.`baby_account`: 99% 00:01 remain
2016-08-29T14:58:04 Copied rows OK.
2016-08-29T14:58:04 Max rows for the rebuild_constraints method: 6168
Determining the method to update foreign keys...
2016-08-29T14:58:04 `baby`.`baby_account_billing_contract`: 21 rows; can use rebuild_constraints
2016-08-29T14:58:04 `baby`.`baby_account_tactics`: too many rows: 13308; must use drop_swap
2016-08-29T14:58:04 Drop-swapping tables...
2016-08-29T14:58:04 Analyzing new table...
2016-08-29T14:58:05 Dropped and swapped tables OK.
Not dropping old table because --no-drop-old-table was specified.
2016-08-29T14:58:05 Dropping triggers...
2016-08-29T14:58:05 Dropped triggers OK.
Successfully altered `baby`.`baby_account`.