pt-online-schema-change的功能是不加锁的情况下更改表。
用法如下:
pt-online-schema-change [OPTIONS] DSN
pt-online-schema-change在不堵塞读写的情况下修改表结构。在DSN(MySQL连接访问)里指定库和表。在没有认真阅读文档和检查你的备份前,不要使用该工具喲!
①给`sakila`.`actor`库表加一列:
pt-online-schema-change --alter "ADD COLUMN c1 INT" D=sakila,t=actor
②修改`sakila`.`actor`库表为InnoDB存储引擎,因为该表已经是一张InnoDB表,所以实际上是以一个不阻塞的方式执行“ OPTIMIZE TABLE ”:
pt-online-schema-change --alter "ENGINE=InnoDB" D=sakila,t=actor
pt-online-schema-change模拟MySQL内部修改表的机制,但是它作用于你想要修改的表的一张拷贝。这意味着原始表不会被加锁,客户端可以继续读取和修改表里面的数据。
pt-online-schema-change通过创建一张将要修改的表的空表拷贝,按照需要修改拷贝表,然后从原始表里面复制记录到新表的方式运行。当数据拷贝完成后,它移走原始表然后以新表替换它。默认情况下,它会删除原始表。
数据复制进程是以小数据块进行的,该数据块的大小是可变的,用以在指定大小的时间内执行(参考--chunk-time选项)。该进程和例如pt-table-checksum的其他工具如何运行非常相似。在复制的过程中,原始表里对数据的任何改动都会映射到新表里,因为该工具会在原始表上创建触发器来更新新表里对应的记录。触发器的使用意味着如果原始表上已经定义了触发器,该工具将无法工作。
拷贝数据到新表完成后,该工具进行一个原子性“ RENAME TABLE ”操作来同时重命名原始表和新表。操作完成后,工具会删除原始表。
外键使该工具的运行复杂化并且引入额外的风险。如果外键关联到该表,原子性重命名原始表和新表的技术将无法工作。模式修改完成后工具必须更新外键去关联新表。该工具支持两种方式来实现,参考--alter-foreign-keys-method选项。
外键也会带来一些副作用。最终的表将和原始表具有相同的外键和索引(除非在你的ALTER语句中指定了不同的),但是这些对象的名称可能会被轻微地改动,以避免在MySQL和InnoDB中的对象名称冲突。
安全起见,除非指定--execute选项,该工具不会改动表,该选项默认不启用。该工具支持各种其他措施来防止额外负载或者其他问题,包括自动检测replicas、连接和进行以下安全检查:
该工具会打印其活动信息到STDOUT以便你可以观察它在做些啥子。在数据拷贝阶段,它打印--progress报告到STDERR。通过指定--print选项获取更多信息。如果指定了--statistics选项,结尾会打印各种内部事件计数的报告,例如:
# Event Count # ====== ===== # INSERT 1
以下为个人本地环境的测试数据。
测试库表数据定义。
mysql> SHOW CREATE TABLE `player`.`player`;
+--------+-----------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Table | Create Table
|+--------+-----------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| player | CREATE TABLE `player` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`number` int(10) unsigned NOT NULL COMMENT 'player number',
`name` varchar(15) NOT NULL COMMENT 'player name',
`role` varchar(15) NOT NULL COMMENT 'player role',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 |
+--------+-----------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set (0.01 sec)
mysql> SELECT * FROM `player`.`player`;
+----+--------+-------+-------------+
| id | number | name | role |
+----+--------+-------+-------------+
| 1 | 1 | hachi | GK |
| 2 | 2 | ni | left back |
| 3 | 3 | san | center back |
| 4 | 4 | yon | center back |
| 5 | 5 | go | right back |
+----+--------+-------+-------------+
5 rows in set (0.00 sec)
干执行(--dry-run打印工具执行过程但不会操作具体表)添加字段。
root@ubuntu:~# pt-online-schema-change -h192.168.112.129 -P3306 -uroot -p123456 --alter "ADD COLUMN remark1 VARCHAR(15) NULL DEFAULT NULL" D=player,t=player --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
Starting a dry run. `player`.`player` will not be altered. Specify --execute instead of --dry-run to alter the table.
Creating new table...
Created new table player._player_new OK.
Altering new table...
Altered `player`.`_player_new` OK.
Not creating triggers because this is a dry run.
Not copying rows because this is a dry run.
Not swapping tables 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.
2018-04-12T21:28:13 Dropping new table...
2018-04-12T21:28:13 Dropped new table OK.
Dry run complete. `player`.`player` was not altered.
执行(--execute)添加字段。
root@ubuntu:~# pt-online-schema-change -h192.168.112.129 -P3306 -uroot -p123456 --alter "ADD COLUMN remark1 VARCHAR(15) NULL DEFAULT NULL" D=player,t=player --execute
No slaves found. See --recursion-method if host ubuntu has slaves.
Not checking slave lag because no slaves were found and --check-slave-lag was not specified.
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
Altering `player`.`player`...
Creating new table...
Created new table player._player_new OK.
Altering new table...
Altered `player`.`_player_new` OK.
2018-04-12T21:29:16 Creating triggers...
2018-04-12T21:29:16 Created triggers OK.
2018-04-12T21:29:16 Copying approximately 5 rows...
2018-04-12T21:29:16 Copied rows OK.
2018-04-12T21:29:16 Analyzing new table...
2018-04-12T21:29:16 Swapping tables...
2018-04-12T21:29:16 Swapped original and new tables OK.
2018-04-12T21:29:16 Dropping old table...
2018-04-12T21:29:16 Dropped old table `player`.`_player_old` OK.
2018-04-12T21:29:16 Dropping triggers...
2018-04-12T21:29:16 Dropped triggers OK.
Successfully altered `player`.`player`.
“修改”存储引擎(这里相当于“ OPTIMIZE TABLE ”)。
root@ubuntu:~# pt-online-schema-change -h192.168.112.129 -P3306 -uroot -p123456 --alter "ENGINE=InnoDB" D=player,t=player --execute
No slaves found. See --recursion-method if host ubuntu has slaves.
Not checking slave lag because no slaves were found and --check-slave-lag was not specified.
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
Altering `player`.`player`...
Creating new table...
Created new table player._player_new OK.
Altering new table...
Altered `player`.`_player_new` OK.
2018-04-12T21:31:45 Creating triggers...
2018-04-12T21:31:45 Created triggers OK.
2018-04-12T21:31:45 Copying approximately 5 rows...
2018-04-12T21:31:45 Copied rows OK.
2018-04-12T21:31:45 Analyzing new table...
2018-04-12T21:31:45 Swapping tables...
2018-04-12T21:31:45 Swapped original and new tables OK.
2018-04-12T21:31:45 Dropping old table...
2018-04-12T21:31:45 Dropped old table `player`.`_player_old` OK.
2018-04-12T21:31:45 Dropping triggers...
2018-04-12T21:31:45 Dropped triggers OK.
Successfully altered `player`.`player`.
吧啦吧啦多打印一些输出。
root@ubuntu:~# pt-online-schema-change -h192.168.112.129 -P3306 -uroot -p123456 --alter "ADD COLUMN remark0 VARCHAR(15) NULL DEFAULT NULL" D=player,t=player --progress=iterations,1 --print --statistics --execute
No slaves found. See --recursion-method if host ubuntu has slaves.
Not checking slave lag because no slaves were found and --check-slave-lag was not specified.
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
Altering `player`.`player`...
Creating new table...
CREATE TABLE `player`.`_player_new` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`number` int(10) unsigned NOT NULL COMMENT 'player number',
`name` varchar(15) NOT NULL COMMENT 'player name',
`role` varchar(15) NOT NULL COMMENT 'player role',
`remark1` varchar(15) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
Created new table player._player_new OK.
Altering new table...
ALTER TABLE `player`.`_player_new` ADD COLUMN remark0 VARCHAR(15) NULL DEFAULT NULL
Altered `player`.`_player_new` OK.
2018-04-12T21:40:39 Creating triggers...
2018-04-12T21:40:39 Created triggers OK.
2018-04-12T21:40:39 Copying approximately 5 rows...
INSERT LOW_PRIORITY IGNORE INTO `player`.`_player_new` (`id`, `number`, `name`, `role`, `remark1`) SELECT `id`, `number`, `name`, `role
`, `remark1` FROM `player`.`player` LOCK IN SHARE MODE /*pt-online-schema-change 5635 copy table*/2018-04-12T21:40:39 Copied rows OK.
2018-04-12T21:40:39 Analyzing new table...
2018-04-12T21:40:39 Swapping tables...
RENAME TABLE `player`.`player` TO `player`.`_player_old`, `player`.`_player_new` TO `player`.`player`
2018-04-12T21:40:39 Swapped original and new tables OK.
2018-04-12T21:40:39 Dropping old table...
DROP TABLE IF EXISTS `player`.`_player_old`
2018-04-12T21:40:39 Dropped old table `player`.`_player_old` OK.
2018-04-12T21:40:39 Dropping triggers...
DROP TRIGGER IF EXISTS `player`.`pt_osc_player_player_del`
DROP TRIGGER IF EXISTS `player`.`pt_osc_player_player_upd`
DROP TRIGGER IF EXISTS `player`.`pt_osc_player_player_ins`
2018-04-12T21:40:39 Dropped triggers OK.
# Event Count
# ====== =====
# INSERT 1
Successfully altered `player`.`player`.
参考:
https://www.percona.com/doc/percona-toolkit/LATEST/pt-online-schema-change.html