### 调研背景

在 mysql 5.5 版本以前，修改表结构如添加索引、修改列，需要锁表，期间不能写入，对于大表这简直是灾难。从5.5特别是5.6里，情况有了好转，支持Online DDL，而在实际alter table过程中还是会引起 data meta lock 问题。pt-online-schema-change是Percona-toolkit一员，通过改进原生ddl的方式，达到不锁表在线修改表结构。

### 工作原理

- 如果存在外键，根据 alter-foreign-keys-method 参数的值，检测外键相关的表，做相应设置的处理。没有使用 alter-foreign-keys-method 指定特定的值，该工具不予执行。
- 创建一个新的空表，其命名规则是：下划线 + 原表名 +_new—-_原表名_new
- 根据 alter 语句，更新新表的表结构。
- 创建触发器，用于记录从拷贝数据开始之后，对源数据表继续进行数据修改的操作记录下来，用于数据拷贝结束后，执行这些操作，保证数据不会丢失。如果表中已经定义了触发器这个工具就不能工作了。
- 拷贝数据，从源数据表中拷贝数据到新表中。
- 修改外键相关的子表，根据修改后的数据，修改外键关联的子表。
- rename 源数据表为 old 表，把新表 rename 为源表名，其通过一个 RENAME TABLE 同时处理两个表，实现原子操作。（RENAME TABLE dbteamdb.user TO dbteamdb._user_old, dbteamdb._user_new TO dbteamdb.user）。
- 将 old 表删除、删除触发器。

### 对数据库影响

- 操作过程中需要对原表更新的数据通过触发器写入新表，该过程中会对原表的读写有一定影响。
- 虽然整个过程中可以不锁表操作，但是在新旧表进行rename操作时会进行加锁操作，该过程中客户端更新操作可能会失败。

| 数据量 | rename操作时间 |
| ------ | -------------- |
| 30W    | < 1s           |
| 2200W  | ≈3s            |

### 使用限制

- 表必须有主键
- 表之前不能有触发器
- rename操作过程中用户操作数据库有可能失败
- 操作过程中会创建临时表，mysql的binlog日志会有所增加

### 总结

可以使用，在使用时，应该尽量选择在业务相对空闲时，至少修改表上的数据操作较低时，执行较为妥当。
由于可能存在一定的风险，在操作之前，建议对数据表进行备份，可以使得操作更安全、可靠。