MySQL-添加索引或字段时如何不锁表

索引的添加MySQL经历了一下几个历程:

一 .在MySQL 5.5版本之前,添加索引具体是这样的:

1.首先创建一张临时表和原表数据结构相同,将你要添加的索引加上。

2.把原表数据导入临时表。

3.删除原表。

4.将临时表重命名为原表。

这样做有很大问题:

首先对于大数据量的导入需要很长的时间,那么在这段时间里新增或修改的数据没办法处理。

其次如果碰上大事务正在新增或更新更新这张原表还会锁表,你还没办法用sql去导入到临时表中。

二 .但在InnoDB 1.0版本开始,支持一种Fast Index(快速索引创建)的方式,简称FIC,他是这样做的:

对于辅助索引的创建,他不需要建临时表,他会直接将原表加S锁,这样就不会有数据导入的问题。

但还是会有些其他问题:

这意味着这加索引的这段时间里这张表只能读,不能增删改。而且不适用主键索引。

三. 针对一,二阶段的问题,Facebook总结并实现了一种在线执行方案-OSC:

1.初始化,检查原表所有的问题,包括主键,触发器,外键等。

2.创建临时表,添加索引字段。

3.创建deltas表,为下一步创建触发器做准备。

4.对原表创建增删改的触发器,触发器产生的草所记录写入到上一步创建的deltas表。

5.开始OSC操作的事务。

6.删除所有辅助索引,再将原表数据通过分片文件写入临时表。

7.将deltas表中产生的记录应用到临时表中。

8.重新创建辅助索引。

10.将原表和临时表交换名字,在这个过程中会锁表,但这个过程很快。

以上便是整个OSC过程,看起来就很复杂,实际的脚本也很复杂,光是核心PHP代码就2000多行,而且有一定局限性,对于分布式无法主从同步。

四.MySQL5.6版本开始支持在线创建--Online DDL,只需一行代码:

以下是对辅助索引的添加:

 ALTER TABLE table_name ADD INDEX  indea_name ,ALGORITHM=INPLACE,LOCK=NONE;

ALGORITHM指定创建或删除索引得算法,有以下几类:

COPY:按照5.1之前的版本,创建临时表的方式。

INPLACE:不需要创建临时表。

DEFAULT:表示根据参数old_alter_table来判断是用COPY还是INPLACE,默认OFF,表示采用INPLACE方式。

 LOCK表示加锁情况:

NONE:不添加任何锁,允许并发。

SHARE:加S锁。

EXCLUSIVE:加X锁,读写都不允许。

DEFAULT:会先判断是否可用NONE,若不能再判断是否可用SHARE模式,最后判断EXCLUSIVE。

Online DDL的原理是则好样的:

1.在创建或删除索引的同时,会将这段时间发生的增删改操作的日志写入一个缓存中,待完成索引后再重新将日志应用到表上,达到数据一致性。这个缓存的小由innodb_online_alter_log_max_size控制,默认128MB。可以根据情况调整。

需要注意的是,在这个过程中,sql不会用到正在创建的索引。

原文地址:https://www.cnblogs.com/lvqiang/p/14412493.html