> For the complete documentation index, see [llms.txt](https://bing.gitbook.io/phper/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bing.gitbook.io/phper/data-base/my-sql/note/pt-online-schema-change.md).

# Pt Online Schema Change

#### 调研背景

在 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日志会有所增加

#### 总结

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