本文共 1765 字,大约阅读时间需要 5 分钟。
在mysql的早期版本中,DDL操作因为锁表会和DML操作发生锁冲突,大大降低并发性。在早期版本中,大部分DDL操作的执行原理就是通过重建表的方式;例如对于索引的添加删除,mysql的操作过程如下:
首先新建Temp table,表结构是 ALTAR TABLE 新定义的结构;
然后把原表中数据导入到这个Temp table;删除原表;最后把临时表rename为原来的表名;因为有复制原表数据,所以会长时间锁表,只能读不能写,DDL操作和DML操作有很严重的冲突。
从mysql5.6开始,很多DDL操作过程都进行了改进,出现了Online DDL。所谓Online DDL就是指这类DDL操作和DML基本上可以不发生冲突(不是绝对不冲突),表在执行DDL操作时同样可以执行DML操作。mysql5.6时只是部分DDL操作online化,到现在绝大部分DDL都是Online DDL。
MySQL各版本中,对于DDL的处理方式是不同的,主要有三种:
1、copy table方式这是innodb最早支持的方式。即重建表方式,先创建一个目标结构的临时表,然后将原表数据复制到临时表,再对临时表rename,完成DDL操作。这种方式原表可读但不可写,并且消耗一倍的存储空间。2、inplace方式
这是在mysql5.5版本里支持的方式。就是直接在原表上进行操作,不会出现数据拷贝。原表同样可读,但不可写。3、online方式
这是mysql5.6.27开始以上的版本出现的方式。与以上两种方式相比,online方式不仅可以读,还可以支持写操作。以下是从mysql5.7官方文档中,列出常用的DDL的执行方式
inplace:为yes是优选项,说明该操作支持inplace方式;
rebuilds table:为no是优选项,大部分情况下是与inplace相反的;permits DML:为yes是优选项,表示支持读写,可以认为该种DDL支持online方式,反之则不支持;only modifies metadata:参考选项,表示该种DDL是否仅仅修改元数据。参考官方文档:
DDL中,create index操作是最常见的,了解其online方式原理十分重要。从上表可以看出创建二级索引操作是支持online的,其实际过程就是改进的inplace方式。
比如为name列(非主键)建立索引时,会遍历聚簇索引,收集name列的记录并插入到新索引中;此过程原表数据可修改,所有涉及到name列的修改记录会保存在Row log中;当遍历完聚簇索引后,再重放Row log中的修改记录,使得新索引与聚簇索引记录达到一致状态。
Row log是一种独占结构,它不是redo log。它以Block的方式管理DML记录的存放,一个Block的大小为由参数innodb_sort_buffer_size控制,默认大小为1M,初始化阶段会申请两个Block。
online创建索引,遵循的是先创建索引数据字典,后填充数据的方式。因此最先创建索引数据字典,之后用户线程可以看到此索引,但由于此索引的状态为ONLINE_INDEX_CREATION,因此索引实际还不会起作用。
在重放row log过程中,如果还有DML操作,那么会继续追加到row log中,在重放最后一个row log block时会锁表,这时不会有追加的DML操作了。
在online add index期间,也会有锁表现象,主要在重放row log时,有两种情况下需要锁表:
1、在使用完一个Block,跳转到下一个Block时,需要短暂锁表,判断下一个Block是否为Row Log的最后一个Block。若不是最后一个,跳转完毕后,释放锁;使用Block内的row log不加锁,用户DML操作仍旧可以进行;2、在使用最后一个Block时,会一直持有锁。此时不允许新的DML操作。保证最后一个Block重放完成之后,新索引与聚簇索引记录达到一致状态。以上两种锁表情况的时间都很短,这种影响是可以接受的。参考文章
转载地址:http://ocbso.baihongyu.com/