MySQL 5.6 使用online DDL不锁表增加字段和索引

创建索引

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

ALTER TABLE tbl_name ADD PRIMARY KEY (column), ALGORITHM=INPLACE, LOCK=NONE;

ALTER TABLE tbl_name ADD COLUMN column_name column_definition, ALGORITHM=INPLACE, LOCK=NONE;

ALTER TABLE `member` ADD `user_from` smallint(1) NOT NULL, ALGORITHM=INPLACE, LOCK=NONE

Performance and Space Requirements

ALTER TABLE操作有两种算法(ALGORITHM)

  • COPY: 操作在原表的副本表上进行,表数据逐行拷贝自原表。不支持并发DML。

  • INPLACE: 操作避免复制表数据,但可能会就地rebuild表。在准备和执行阶段,可能会短暂地独占元数据锁。通常,支持并发DML

ALGORITHM 子句是可选项。如果没有指定ALGORITHM ,或者指定ALGORITHM=DEFAULT,MySQL则在支持的引擎和alter操作使用 ALGORITHM=INPLACE;否则使用 ALGORITHM=COPY

注意
分区表不支持ALGORITHM=DEFAULT, ALGORITHM=INPLACE, and ALGORITHM=COPY
MySQL 5.6.11及以后的版本,分区表使用 ALGORITHM=1 and ALGORITHM=2 来升级/降级。
参见Section 13.1.7.1, “ALTER TABLE Partition Operations”。

指定ALGORITHM子句需要使用的操作和存储引擎支持,否则会报错。指派ALGORITHM=DEFAULT等同于忽略配置。

使用COPY算法的ALTER TABLE操作,依赖其他表修改操作来完成。在副本表更改后,将复制数据,删除原始表,并将副本表重命名为原始表的名称。在执行 ALTER TABLE 操作时,其他会话可以读取原始表 (with the exception noted shortly)。在ALTER table操作开始后,对表的更新和写入被暂停,直到新表准备就绪,然后自动重定向到新表。临时表在原始表的同目录中创建,除非RENAME TO到其他目录。

前面提到的 exceptionALTER TABLE 在准备安装新版本的表.frm文件时,会阻止读取(不仅是写),丢弃旧文件,从表&表定义缓存中清除过期表结构。这时,它必须独占锁。为此,要等待当前读结束,并阻止新的读写。

使用COPY算法的ALTER TABLE操作可防止并发DML,允许并发查询。也就是说,table-copying操作至少限制在LOCK=SHARED(允许查询,但不允许DML)。LOCK=EXCLUSIVE则阻止DML和查询,进一步限制了支持LOCK子句的操作的并发性。
参见Concurrency Control

Note
MySQL 5.6,LOCK在分区表上不支持 ALTER TABLE 操作

要强制将COPY算法用于本来不使用其的ALTER TABLE操作,需要开启 old_alter_table 系统变量,或指定ALGORITHM=COPY。如果old_alter_table和非默认值的ALGORITHM冲突,则ALGORITHM子句优先。

对于InnoDB表,对驻留在共享表空间(如 system tablespace)中的表,使用COPY算法的ALTER TABLE操作会增加表空间的使用量。这些操作需要同增加索引一样多的额外空间。对于驻留在共享表空间中的表,操作使用的额外空间不会释放回操作系统,as it is for a table that resides in a file-per-table tablespace。
关于空间需求参见Section 14.13.3, “Online DDL Space Requirements”

使用INPLACE算法的ALTER TABLE操作:

  • InnoDB online DDL特性支持的ALTER TABLE操作。参见 Section 14.13.1, “Online DDL Operations”.

  • 重命名表。MySQL重命名与表tbl_name相关的文件,无需拷贝。也可以使用RENAME TABLE来重命名表。参见 Section 13.1.32, “RENAME TABLE Statement”.) 。权限需要手动修改,原表权限不会迁移到重命名后的表。

  • 只修改表元数据的操作。这些是实时操作,因为服务器仅更改表.frm 文件,不创建表内容。元数据操作包含:

    • 重命名列
    • 改变列的默认值 ,NDB表不适用。参见Limitations of NDB online operations。
    • 修改枚举ENUMor集合SET列的定义,通过在有效成员值列表的末尾添加新的枚举或集合成员,只要数据类型的存储大小不变。比如,添加一个成员到拥有8个成员的某SET列,会将每个值所需的存储空间从1字节更改为2字节,那么需要table copy。 在列表中间添加成员会导致现有成员重新编号,也需要table copy。
  • InnoDBNDB表,创建、删除二级索引。参见Section 14.13, “InnoDB and Online DDL”。

  • 对于NDB表,在variable-width列上增加、删除索引的操作。这些操作在线进行,无需table copying ,并且在大部分时间内不会阻止并发DML操作。参见 Section 18.6.11, “Online Operations with ALTER TABLE in NDB Cluster”。

从MySQL 5.6.16开始,对于ADD COLUMN, CHANGE COLUMN, MODIFY COLUMN, ADD INDEX, and FORCE操作,ALTER TABLE会将MySQL 5.5临时列升级为5.6格式。无法使用 INPLACE算法完成此转换,因为必须rebuild表,因此该情况下指定ALGORITHM=INPLACE会报错。如果需要,指定 ALGORITHM=COPY

NDB Cluster支持在MySQL NDB Cluster 7.3及更高版本中,使用 ALGORITHM=INPLACE 语法进行在线ALTER TABLE操作。NDB集群还支持NDB特有的旧语法的ONLINE and OFFLINE关键字。这些关键字从MySQL NDB Cluster 7.3开始就被弃用;MySQL NDB Cluster 7.4中仍然支持它们,但在NDB Cluster的未来版本中可能会删除它们。参见 Section 18.6.11, “Online Operations with ALTER TABLE in NDB Cluster”。

根据KEY来对表分区的多列索引,如果ALTER TABLE操作作用于该多列索引上变更了列的顺序,则只能使用ALGORITHM=COPY

MySQL NDB Cluster 7.3(及更高版本)支持使用ALGORITHM=INPLACE语法(与标准MySQL服务器相同)的在线操作。NDB Cluster 7.3和7.4还继续支持使用ONLINE and OFFLINE关键字进行在线ALTER TABLE操作,以实现向后兼容性,但NDB 7.3和7.4中不推荐使用这些关键字,并且从NDB 7.5起不再支持这些关键字。NDB不支持在线变更表空间。参见Section 18.6.11, “Online Operations with ALTER TABLE in NDB Cluster”。

ADD PARTITION, DROP PARTITION, COALESCE PARTITION, REBUILD PARTITION, or REORGANIZE PARTITION这些ALTER TABLE 操作不会创建临时表 (NDB表除外);然而, 这些操作确实可以创建临时分区文件。

对于RANGE or LIST分区,ADD or DROP是实时或几乎实时的操作。
对于HASH or KEY分区,ADD or COALESCE操作从所有分区拷贝数据,除非使用了LINEAR HASH or LINEAR KEY;这实际上与创建新表相同,尽管ADD or COALESCE操作是逐个分区执行的。
REORGANIZE操作只复制已更改的分区,不接触未更改的分区。

对于MyISAM表,通过将myisam_sort_buffer_size系统变量调高,可以加快索引的重建速度,这是alter过程中最慢的部分。

并发控制 Concurrency Control

对于支持Concurrency Control的ALTER TABLE操作,可以使用LOCK子句在表被alter时控制表上并发读写的级别。
非默认值的指定,使得在alter操作期间,您可以请求一定量的并发/独占访问,并可以在请求的锁定程度不再可用时停止操作。

  1. LOCK = DEFAULT
    如果支持,允许并发读取。
    如果不支持并发读取,支持并发读,则允许并发读。
    如果也不支持并发读,则强制排它访问。
  2. LOCK = NONE
    允许并发读写。如果不支持并发读写,则报错。
  3. LOCK = SHARED
    允许并发读取,不允许块写入。即便给定的ALGORITHM子句和 ALTER TABLE操作支持并发写,也不可以。如果不支持并发读,则报错。
  4. LOCK = EXCLUSIVE
    强制排它访问。即便给定的ALGORITHM子句和 ALTER TABLE操作支持并发读/写,也要执行此操作。

online DDL的空间要求:

由于online DDL执行期间需要创建临时表空间文件用于存储数据,以及申请row log记录DML操作,所以在执行DDL前应该先确认空间上是否满足要求,否则由于空间不够很可能导致操作失败,而进行回滚。

1、row log空间:row log空间每次申请的大小由 innodb_sort_buffer_size决定,最大值由innodb_online_alter_log_max_size,该值默认为128M,支持动态修改。对于更新频繁的表来讲,如果预计在DDL期间对表的更新操作存储可能超过128M时,需要为本次操作增大该值。当然如果不涉及rebuild操作时,不需要考虑该值。如果提示DB_ONLINE_LOG_TOO_BIG错误,则是由innodb_online_alter_log_max_size空间不足造成的。

2、索引排序空间:如果DDL操作涉及二级索引的创建,会在MySQL临时目录产生临时排序文件,将中间的排序结果写入文件,最终将内容合并到最终表或索引中,然后自动删除临时排序文件。这个路径默认为mysql全局参数tmpdir指定(默认值为/tmp,如果手动指定了innodb_tmpdir参数的路径,则tmpdir会被覆盖),且不会在原始表的目录中创建临时排序文件。tmpdir需要保证能够容纳要创建的二级索引,临时排序文件最大可能需要的空间等于表中的数据量加上索引,否则执行将报错。(官方文档的说明,实际测试200万的表加索引,并未生成临时排序文件,这有点奇怪)

3、中间表空间:如果DDL操作涉及rebuild表,则会在原表所在目录创建临时表空间文件(以#sql开头),临时表空间大小需要等于原表大小,重建完成后会自动重命名临时表空间,删除原表空间。所以执行rebuild操作时需要保证原表所在路径下有足够空间

参考资料 :

https://c4ys.com/archives/1943

MySQL 5.6 Reference Manual / The InnoDB Storage Engine
InnoDB and Online DDL
Online DDL Operations
CREATE INDEX Statement
ALTER TABLE Statement

你可能感兴趣的:(MySQL 5.6 使用online DDL不锁表增加字段和索引)