Online DDL定义
什么是Online DDL?
Online DDL 就是在线对表进行表结构(DDL)的修改(却不影响其他用户对表的增删改查操作)。
为什么要Online?
Online DDL可以支持 DDL与DML操作同时进行,降低DDL时刻对业务产生的延迟。
不Online又如何?
早期5.5及前版本的MySQL,没有Online的功能,在进行DDL操作的时候,整个表都是被阻塞的,其他用户或者业务对表进行数据修改的时候(DML),就会产生阻塞,生产环境会降低业务的响应度和可用性,直到你的DDL完成后才能进行其他数据修改的操作,这通常是不能接受的。
Online DDL通常包含那些操作或命令?
Online DDL通常包含以下几种类型:
-
索引相关操作:新建索引,删除索引
-
主键相关操作:增加主键,删除主键
-
列相关操作:
- 新增列
- 删除列
- 重命名列
- 设置/删除列的缺省值
- 修改列类型
- 扩展字符串列的长度
- 修改自增长auto_increment序列的值
- 设置列为空或者非空NULL/NOT NULL
- 修改枚举类型列NEMU或者集合类型SET的列定义
-
衍生列(Generated Column)相关操作:增加修改删除Virtual或者Store列
-
外键相关操作:增加/删除外键
-
表相关操作:
- 改变表的row_format
- 改变表的key_block_size
- 改变表的字符集
- 优化表optimize table
- 重建表:alter table force/ alter table engine=innodb;
- 重命名表:ALTER TABLE old_tbl_name RENAME TO new_tbl_name
-
表空间相关操作:修改表空间或者给表空间加密
-
分区相关操作:增加分区,删除分区等操作
Online DDL内部原理
MySQL5.6之前早期版本DDL实现原理
早期版本支持copy table 和inplace方式来支持DDL操作,原理如下:
- copy方式
- 新建临时表,在临时表上执行DDL语句
- 锁原表,不允许DML,允许查询
- 拷贝数据
- 拷贝完成后的那一时刻原表禁止操作(读写都不可以)
- 进行rename操作,完成DDL过程
- inplace方式 (仅支持索引的创建与删除)
- 新建frm临时文件
- 锁原表,不允许DML,允许查询
- 按照聚集索引的顺序,查询数据,找到需要的索引列数据,排序后插入到新的索引页中
- 原表禁止操作(读写都不可以)
- 进行rename操作,替换frm文件,完成DDL过程
inplace与copy的最大区别就是 不用拷贝数据,节省时间和存储空间,SQL执行速度大大提升,但是inplace仅仅支持索引的创建与删除,其他的DDL还都是copy方式。
早期版本无论是copy还是inplace,在DDL期间,表都不可以对数据进行修改操作insert,update,delete 只能查询,对业务的影响还是太大了。
MySQL5.6以后版本DDL实现原理Online
为了改善早期版本DDL的问题,5.6后推出了Online DDL,在做DDL期间允许对表数据的修改(DML)操作,这相对于以前版本的MySQL DDL,大大提高了服务的连续性。
在online DDL中,也包含了几种方式/算法:Copy,Inplace,Instant(8.0版本),详情参考下图示例:
Online DDL在内部实现主要分以下三个阶段:
一, 初始化
1. 对表加元数据共享升级锁,并升级为排他锁。(此时DML不能并行)
2. 在原表所在的路径下创建.frm和.ibd临时中转文件(no-rebuild除创建二级索引外只创建.frm文件,其中添加二级索引操作最为特殊,该操作属于no-rebuild不会生成.ibd,但实际上对.ibd文件却做了修改,该操作会在参数tmpdir指定路径下生成临时文件,用于存储索引排序结果,然后再合并到.ibd文件中)
3. 申请row log空间,用于存放DDL执行阶段产生的DML操作。(no-rebuild不需要)
二, 执行
1、释放排他锁,保留元数据共享升级锁(此时DML可以并行)。
2、扫描原表主键以及二级索引的所有数据页,生成 B+ 树,存储到临时文件中;
3、将所有对原表的DML操作记录在日志文件row log中
注:如果只修改元数据部分(no-rebuild)该阶段只是修改.frm文件,不需要其他操作,也不需要申请row log
三, 提交
1、升级元数据共享升级锁,产生排他锁锁表(此时DML不能并行)。
2、重做row log中的内容。(no-rebuild不需要)
3、重命名原表文件,将临时文件改名为原表文件名,删除原表文件
4、提交事务,变更完成。
说明:在DDL期间产生的数据,会按照正常操作一样,写入原表,记redolog、undolog、binlog,并同步到从库去执行,只是额外会记录在row log中,并且写入row log的操作本身也会记录redolog,而在提交阶段才进行row log重做,此阶段会锁表,此时主库(新表空间+row log)和从库(表空间)数据是一致的,在主库DDL操作执行完成并提交,这个DDL才会写入binlog传到从库执行,在从库执行该DDL时,这个DDL对于从库本地来讲仍然是online的,也就是在从库本地直接写入数据是不会阻塞的,也会像主库一样产生row log。但是对于主库同步过来DML,此时会被阻塞,是offline的,DDL是排他锁的在复制线程中也是一样,所以不只会阻塞该表,而是后续所有从主库同步过来的操作(主要是在复制线程并行时会排他,同一时间只有他自己在执行)。所以大表的DDL操作,会造成同步延迟。
Online DDL限制及注意事项
- online DDL 在第一阶段和第三阶段会有个MDL锁的情况,这个锁获取虽然很快,但是如果涉及到的表存在大事物,长事物,慢查询等将可能引发会话阻塞。
- 在Online ddl执行操作期间,后台进程会将增量数据记录到临时日志里面,但这个日志是有大小限制的,初始大小等于参数innodb_sort_buffer_size,最大大小由参数innodb_Online_alter_log_max_size进行控制,默认为128M,当临时日志超过128M时,ddl操作会失败终止。
- 在执行Online ddl的时候要需要注意服务器磁盘空间,io,cpu资源的使用情况,特别是存在rebuild-table操作的时候,由于需要重建表,至少需要表一倍的磁盘空间,并且由于操作的数据量大,将会占用一定的IO,CPU资源。
- online DDL会产生主从延迟,要评估应用是否有影响。
- 要确认 DDL类型 是否支持Online DDL
相关总结
- 所谓的online DDL虽然三个阶段(准备、执行、提交)中,有两个阶段(初始化、提交)都无法进行CRUD,但实际上,整个DDL中执行阶段时间占比最长,例如30分钟的DDL,准备+提交阶段只占用不到1分钟的时间,剩下的29分钟都在执行,那么对于业务层来说,绝大部分时间都是能正常访问的,所以就做到了Oline DDL了。
- 请不要把online DDL理解成绝对的可以在线做,对业务无影响。
- 尽量不要在业务高峰期间进行DDL,即使是online DDL;
- 对于大表的DDL操作,最好在测试库上做一遍,预估下时间(线上和测试环境数据量大概一致的情况)