暂无图片
暂无图片
4
暂无图片
暂无图片
暂无图片

MySQL Online DDL原理浅析及使用注意事项

原创 Rock Yan 云和恩墨 2023-05-30
3168

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通常包含以下几种类型:

  1. 索引相关操作:新建索引,删除索引

  2. 主键相关操作:增加主键,删除主键

  3. 列相关操作:

    • 新增列
    • 删除列
    • 重命名列
    • 设置/删除列的缺省值
    • 修改列类型
    • 扩展字符串列的长度
    • 修改自增长auto_increment序列的值
    • 设置列为空或者非空NULL/NOT NULL
    • 修改枚举类型列NEMU或者集合类型SET的列定义
  4. 衍生列(Generated Column)相关操作:增加修改删除Virtual或者Store列

  5. 外键相关操作:增加/删除外键

  6. 表相关操作:

    • 改变表的row_format
    • 改变表的key_block_size
    • 改变表的字符集
    • 优化表optimize table
    • 重建表:alter table force/ alter table engine=innodb;
    • 重命名表:ALTER TABLE old_tbl_name RENAME TO new_tbl_name
  7. 表空间相关操作:修改表空间或者给表空间加密

  8. 分区相关操作:增加分区,删除分区等操作

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.png

 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限制及注意事项

  1. online DDL 在第一阶段和第三阶段会有个MDL锁的情况,这个锁获取虽然很快,但是如果涉及到的表存在大事物,长事物,慢查询等将可能引发会话阻塞。
  2. 在Online ddl执行操作期间,后台进程会将增量数据记录到临时日志里面,但这个日志是有大小限制的,初始大小等于参数innodb_sort_buffer_size,最大大小由参数innodb_Online_alter_log_max_size进行控制,默认为128M,当临时日志超过128M时,ddl操作会失败终止。
  3. 在执行Online ddl的时候要需要注意服务器磁盘空间,io,cpu资源的使用情况,特别是存在rebuild-table操作的时候,由于需要重建表,至少需要表一倍的磁盘空间,并且由于操作的数据量大,将会占用一定的IO,CPU资源。
  4. online DDL会产生主从延迟,要评估应用是否有影响。
  5. 要确认 DDL类型 是否支持Online DDL

相关总结

  • 所谓的online DDL虽然三个阶段(准备、执行、提交)中,有两个阶段(初始化、提交)都无法进行CRUD,但实际上,整个DDL中执行阶段时间占比最长,例如30分钟的DDL,准备+提交阶段只占用不到1分钟的时间,剩下的29分钟都在执行,那么对于业务层来说,绝大部分时间都是能正常访问的,所以就做到了Oline DDL了。
  • 请不要把online DDL理解成绝对的可以在线做,对业务无影响。
  • 尽量不要在业务高峰期间进行DDL,即使是online DDL;
  • 对于大表的DDL操作,最好在测试库上做一遍,预估下时间(线上和测试环境数据量大概一致的情况)
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论