MySQL基础篇–在线DDL归纳总结

工具在线DDL

pt-osc原理

pt-online-schema-change
pt-osc工作流程:
1、检查更改表是否有主键或唯一索引,是否有触发器
2、检查修改表的表结构,创建一个临时表,在新表上执行ALTER TABLE语句
3、在源表上创建三个触发器分别对于INSERT UPDATE DELETE操作

触发器来应用DDL执行期间对表所做的DML操作,每种DML操作均对应一个触发器
delete变为delete ignore,update和insert均转换为replace into

4、从源表拷贝数据到临时表,在拷贝过程中,对源表的更新操作会写入到新建表中

在拷表select时需要进行当前读(lock in shared mode)并与insert组成一个事务,
避免快照读导致增量的delete操作丢失

5、将临时表和源表rename(需要元数据修改锁,需要短时间锁表)
6、删除源表和触发器,完成表结构的修改。

gh-ost原理

1、 gh-ost 首先连接到主库上,根据 alter 语句创建幽灵表_tablename_gho;
2、 然后gh-ost作为一个备库连接到主库上,一边在主库上拷贝已有的数据到幽灵表,
一边从主库上拉取增量数据的 binlog,然后不断的把 binlog 应用回主库幽灵表;
3、 等待全部数据同步完成,进行cut-over,即进行幽灵表和原表切换。cut-over是最后一步,
锁住主库的源表,等待binlog应用完毕,然后替换gh-ost幽灵表为源表。gh-ost在执行中,
会在原本的binlog event里面增加hint和心跳包,用来控制整个流程的进度,检测状态等。

原生在线DDL

mysql online ddl

自 MySQL 5.6 起,MySQL 原生支持 Online DDL,即在执行 DDL 期间允许执行DML(insert、update、delete)。了解 Online DDL 先了解一下之前 DDL 的 2 种算法 copy 和 inplace。

Copy方式

1、按照原表定义创建一个新的临时表
2、对原表加写锁(禁止DML,允许select)
3、步骤1)建立的临时表执行DDL
4、将原表中的数据copy到临时表
5、释放原表的写锁
6、将原表删除,并将临时表重命名为原表
可见,采用 copy 方式期间需要锁表,禁止 DML,因此是非 Online 的。
比如:删除主键、修改列类型、修改字符集,这些操作会导致行记录格式发生变化(无法通过全量+增量实现 Online)。

Inplace方式

在原表上进行更改,不需要生成临时表,不需要进行数据copy的过程。
根据是否行记录格式,分为两类:
rebuild:需要重建表(重新组织聚簇索引)。
比如 optimize table、添加索引、添加/删除列、修改列 NULL/NOT NULL 属性等;
no-rebuild:不需要重建表,只需要修改表的元数据
比如删除索引、修改列名、修改列默认值、修改列自增值等。
对于 rebuild 方式实现 Online 是通过缓存 DDL 期间的 DML,待 DDL 完成之后,将 DML 应用到表上来实现的。例如,执行一个 alter table A engine=InnoDB; 重建表的 DDL 其大致流程如下:
1、建立一个临时文件,扫描表A主键的所有数据页;
2、用数据页中表A的记录生成B+树,存储到临时文件中;
3、生成临时文件的过程中,将所有对A的操作记录在一个日志文件(row log)中;
4、临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑数据上与表A相同的数据文件;
5、用临时文件替换表A的数据文件。
说明:
在 copy 数据到新表期间,在原表上是加的 MDL 读锁(允许 DML,禁止 DDL)
在应用增量期间对原表加 MDL 写锁(禁止 DML 和 DDL)
根据表A重建出来的数据是放在 tmp_file 里的,这个临时文件是 InnoDB 在内部创建出来的,
整个 DDL 过程都在 InnoDB 内部完成。
对于 server 层来说,没有把数据挪动到临时表,是一个原地操作,这就是“inplace”名称的来源。

总结

(1)pt-osc、gh-ost、原生 Online DDL copy 方式(实际上是非 Online),都是需要 copy 原表数据到一个新表,这个是非常耗时的;

(2)pt-osc 采用触发器实现应用 DDL 期间的 DML, gh-ost 通过 binlog 应用 DDL 期间的 DML,理论上触发器会有一定的负载,且 gh-ost 可以从从库上拉取binlog,对主库的影响更小;

(3)原生 Online DDL 中 Inplace 方式,对于 no-rebuild 方式,不需要重建表,只需要修改表的元数据,这个是非常快的; (比如删除索引、修改列名、修改列默认值、修改列自增值等)

发表评论

相关文章