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

浅析MySQL Online DDL原理的演进

MySQL技术小栈 2021-08-10
1562
背景



数据库版本5.7.x 在执行ALTER TABLE ADD COLUMN语句时,报了Duplicate entry...的错误;


两张表大小分别为:千万行级别



         

原因定位


Concurrent DML makes changes to the table that are allowed with the original table definition,but not with the new one.The operation only fails at the very end,when MySQL tries to apply all the changes from concurrent DML statements.


For example,

you might insert duplicate values into a column while a unique index is being created,or you might insert NULL values into a column while creating a primary key index on that column.

The changes made by the concurrent DML take precedence,and the ALTER TABLE operation is effectively rolled back.





原因:

下方 ' rebuild表中第10步 ' 中应用DML时,在唯一索引上插入了重复的值,导致alter table操作被回滚;


更改语句为:

ALTER TABLE t1 xx....xx,ALGORITHM=inplace, LOCK=SHARED;


官网链接:

https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-failure-conditions.html







rebuild表时,Online DDL的关键流程说明:


1. 持有 MDL_SHARED_UPGRADABLE 锁,检测表时是否存在

2. 升级到 MDL_EXCLUSIVE 锁,禁止读写

3. 更新数据字典对象

4. 分配row_log对象记录增量

5. 生成新表

6. 降级为 MDL_SHARED_UPGRADABLE ,允许对原表进行读写(wait_while_table_is_used)

7. 用DDL事务的上下文,扫描老表中对该事务可见的数据,并用merge排序,最后插入到新表。

8. 在执行期间,原表的读写不阻塞,增量应用到原表中,并且会记录到row_log中

9. 进入commit阶段,升级到 MDL_EXCLUSIVE 锁,禁止读写

10. 在新表中apply row_log里的增量(row_log_apply)

11. 更新innodb的数据字典表

12. 提交DDL事务

13. 重命名新表的ibd文件

(参考:阿里数据库内核月报)





online DDL说明



NO.1

发展历程


MySQL Online DDL这个特性是在MySQL5.6.7开始支持的,更早期版本的MySQL进行DDL操作时,会阻塞DML,


我们常说的online DDL,其实是从DML操作的角度描述的,如果DDL操作不阻塞DML,那么这个DDL就是online的。


           

NO.2

算法说明


MySQL 5.7 支持COPY、INPLACE

MySQL 8.0 支持COPY、INPLACE、INSTANT(8.0.12版本引入)

           

- copy方式:

拷贝方式改表;是指DDL时,会生成(临时)新表,将原表数据逐行拷贝到新表中,在此期间会阻塞DML;


步骤:

1. 创建与原表结构定义一致的临时表;

2. 对原表加锁,不允许执行DML,但允许查询;

3. 在临时表上执行DDL语句;

4. 逐行拷贝原表数据到临时表;

5. 原表与临时表进行RENAME操作,加锁不允许读写直至DDL完成。




- Inplace 方式:

原地改表,无需拷贝全表数据到新表,在操作准备和执行阶段,可能会短时间内持有表上的排他元数据锁,除此外,DDL期间不会阻塞DML;在InnoDB层完成, 不需要使用Redo log等。


步骤:

1. 创建临时的frm文件;

2. 对原表加锁,不允许执行DML,但允许查询;

3. 根据聚集索引的顺序,构造新的索引项,按照顺序插入新索引页;

4. 升级原表上的锁,不允许读写操作;

5. 替换原表的frm文件,完成DDL操作。


 


- INSTANT 方式:

只需修改数据字典中的元数据,无需拷贝数据也无需重建整表,同样,也无需加排他MDL锁,原表数据也不受影响,整个DDL过程几乎是瞬间完成的,也不会阻塞DML;

       

NO.3

并发控制(锁)说明

       

ALTER TABLELOCK

ALTER TABLE t1 ...., ALGORITHM=...., LOCK=....;


//允许并发查询和DML操作

LOCK=NONE

               

//允许并发查询,但不允许DML操作

LOCK=SHARED

               

//允许尽可能多的并发查询或DML操作,没指定LOCK选项默认就为DEFAULT

LOCK=DEFAULT

               

//不允许并发查询和DML操作

LOCK=EXCLUSIVE


说明:          

alter table的变更按照 INSTANT → inplac → copy这个顺序从性能低到性能高的逐个尝试使用;

锁控制按照 NONE → shared → EXCLUSIVE 这个顺序逐步尝试通过加锁阻塞DML加快完成变更操作。

       


NO.4

示例语句


//执行速度快,对业务影响小;

ALTER TABLE t1 xx....xx,ALGORITHM=instant;

注意:如不支持则会报错:ERROR 1845 (0A000): ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=COPY/INPLACE.

                

//执行时间长;不加锁;几乎不影响业务读写,变更不使用额外磁盘空间

ALTER TABLE t1 xx....xx,ALGORITHM=inplace, LOCK=NONE;

                

//执行时间比LOCK=NONE短,写会受到mdl锁阻塞,变更不使用额外磁盘空间

ALTER TABLE t1 xx....xx,ALGORITHM=inplace, LOCK=SHARED;

                

       

//执行时间比LOCK=NONE短,读写会受到mdl锁阻塞,变更不使用额外磁盘空间

ALTER TABLE t1 xx....xx,ALGORITHM=inplace, LOCK=EXCLUSIVE;

                

//如果不知道如何设置上面的选项,可以设置成 DEFAULT

ALTER TABLE t1 xx....xx,ALGORITHM=inplace, LOCK=DEFAULT;

                


NO.5

各版本支持说明


https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.html

https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html

https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html

                


NO.6

注意事项

                

[ 无论执行的DDL语句是复杂还是简单, 都需要选择在业务低峰期进行操作 ]

                

- 空间需求

                


临时日志文件大小(innodb_online_alter_log_max_size),当DDL执行过程当中允许并发执行DML操作时的日志大小需求。
                        
临时排序文件大小(tmpdir),当DDL执行过程中表需要rebuild时临时排序文件是放在tmpdir指定的路径下的,需要保证该路径下的磁盘空间充足。
                        
临时排序文件都足够容纳所有二级索引以及聚簇索引的主键列,最终合并到新表或索引后,临时排序文件会被删除。
 
在MySQL5.7.11及之后版本当中新增系统参数innodb_tmpdir专门用来指定Online DDL产生排序文件的路径。
                        
临时中间表文件大小当有些DDL执行过程中表需要rebuild时会在当前表所在路径下产生临时中间表文件,临时中间表文件大小可能需要与原表大小一致,在DDL执行过程当中产生。


-合并拆分同表的DDL操作

                

早期不支持Online DDL时通常将同一张表中的多个DDL合并一起执行,以便减少多次rebuild表带来的性能消耗;现在Online DDL特性出现之后,可以通过COPY方式和INPLACE方式来进行分类并合并分组。


其中INPLACE方式又可以根据是否rebuild表来进行分组合并,尽量减少DDL对系统的CPU、I/O资源的影响。

     

  

-对于一些大表进行Online DDL并需要重建表的操作

               

现在还没有机制可以做到暂停Online DDL的操作或者限制Online DDL对服务器 CPU、I/O资源的使用;如果Online DDL执行失败,则回滚有可能会是一项昂贵的操作;


执行时间过长的Online DDL可能会导致主从复制的延迟,因为主 库在执行DDL时可能允许DML并发操作,而在从库只能在执行完DDL语句之后再进行应用DML语句操作。



文章转载自MySQL技术小栈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论