一、概述

登录后复制
在线DDL之快速增加列(秒级别的),并不会造成业务抖动。该功能自 MySQL 8.0.12 版本引入,是由腾讯游戏DBA团队贡献,此功能只适
用于 InnoDB 表。实际上MySQL 5.7就已支持 Online DDL,虽说大部分 DDL 不影响对表DML操作,但是依然会消耗非常多的时间,且占用
额外的磁盘空间,并会造成主从延迟,或者影响表的查询速度。有了这个ALGORITHM=INSTANT 就可应对瞬息万变的需求了。

MySQL在大型表上的 DDL 会带来耗时较久、负载较高、额外空间占用、MDL、主从同步延时等情况。需要特别引起重视,而MySQL的DDL有很
多种方法。
MySQL本身自带三种方法,分别是:copy、inplace、instant。copy算法为最古老的算法,在MySQL5.5及以下为默认算法。
从MySQL5.6开始,引入了inplace算法并且默认使用。inplace算法还包含两种类型:rebuild-table 和 not-rebuild-table。
MySQL使用inplace算法时,会自动判断,能使用not-rebuild-table的情况下会尽量使用,不能的时候才会使用rebuild-table。
当DDL涉及到主键和全文索引相关的操作时,无法使用 not-rebuild-table,必须使用 rebuild-table。其他情况下都会使用 not-rebuild-table。
从MySQL8.0.12开始,引入了instant算法并且默认使用。目前instant算法只支持增加列等少量DDL类型的操作,其他类型仍然会默认使用inplace。

有一些第三方工具也可以实现DDL操作,最常见的是percona的pt-online-schema-change工具(简称为 pt-osc),和github的gh-ost工具,
均支持 MySQL 5.5 以上的版本。

》》各类工具的对比

登录后复制
一般情况下的建议:如果使用的是 MySQL 5.5 或者 MySQL 5.6,推荐使用 gh-ost
如果使用的是 MySQL 5.7,索引等不涉及修改数据的操作,建议使用默认的 inplace 算法。如果涉及到修改数据(例如增加列),不关心主
从同步延时的情况下使用默认的 inplace 算法,关心主从同步延时的情况下使用 gh-ost
如果使用的是 MySQL 8.0,推荐使用 MySQL 默认的算法设置,在语句不支持 instant 算法并且在意主从同步延时的情况下使用gh-ost

二、MySQL DDL 的原理简析

1、copy 算法

较简单的实现方法,MySQL 会建立一个新的临时表,把源表的所有数据写入到临时表,在此期间无法对源表进行数据写入。MySQL在完成临时表的写入之后,用临时表替换掉源表。这个算法主要被早期(<=5.5)版本所使用。

2、inplace 算法

从 5.6 开始,常用的 DDL 都默认使用这个算法。inplace 算法包含两类:inplace-no-rebuild 和 inplace-rebuild,两者的主要差异在于是否需要重建源表。

inplace 算法的操作阶段主要分为三个:Prepare阶段: - 创建新的临时 frm 文件(与 InnoDB 无关)。 - 持有 EXCLUSIVE-MDL 锁,禁止读写。 - 根据 alter 类型,确定执行方式(copy,online-rebuild,online-not-rebuild)。 更新数据字典的内存对象。 - 分配 row_log 对象记录数据变更的增量(仅 rebuild 类型需要)。 - 生成新的临时ibd文件 new_table(仅rebuild类型需要)。

Execute 阶段:降级EXCLUSIVE-MDL锁,允许读写。扫描old_table聚集索引(主键)中的每一条记录 rec。遍历new_table的聚集索引和二级索引,逐一处理。根据 rec 构造对应的索引项。将构造索引项插入 sort_buffer 块排序。将 sort_buffer 块更新到 new_table 的索引上。记录 online-ddl 执行过程中产生的增量(仅 rebuild 类型需要)。重放 row_log 中的操作到 new_table 的索引上(not-rebuild 数据是在原表上更新)。重放 row_log 中的DML操作到 new_table 的数据行上。

Commit阶段:当前 Block 为 row_log 最后一个时,禁止读写,升级到 EXCLUSIVE-MDL 锁。重做 row_log 中最后一部分增量。更新 innodb 的数据字典表。提交事务(刷事务的 redo 日志)。修改统计信息。rename 临时 ibd 文件,frm文件。变更完成,释放 EXCLUSIVE-MDL 锁。

3、instant 算法

MySQL 8.0.12 才提出的新算法,目前只支持添加列等少量操作,利用 8.0 新的表结构设计,可以直接修改表的 metadata 数据,省掉了 rebuild 的过程,极大的缩短了 DDL 语句的执行时间。

4、pt-online-schema-change

借鉴了 copy 算法的思路,由外部工具来完成临时表的建立,数据同步,用临时表替换源表这三个步骤。其中数据同步是利用 MySQL 的触发器来实现的,会少量影响到线上业务的 QPS 及 SQL 响应时间。

三、mysql 8.0特性instant add column

1、instant add column原理

mysql数据库针对亿级别的大表加字段是痛苦的,需要对表进行重建,MySQL 5.7 支持 Online DDL,大部分 DDL 不影响对表的读取和写入,但是依然会消耗非常多的时间,且占用额外的磁盘空间,并会造成主从延迟。所以大表 DDL 仍是一件令 DBA 头痛的事。而mysql8.0使用instant ADD COLUMN特性,只需很短的时间,字段就加好了,享受MongoDB那样的非结构化存储的灵活方便,无形中减少了开发的工作量。

快速加列采用的是 instant 算法,使得添加列时不再需要 rebuild 整个表,只需要在表的 metadata 中记录新增列的基本信息即可。在 alter 语句后增加 ALGORITHM=INSTANT 即代表使用 instant 算法, 如果未明确指定,则支持 instant 算法的操作会默认使用。如果 ALGORITHM=INSTANT 指定但不支持,则操作立即失败并显示错误。

下表概述了对列操作的在线 DDL 支持。星号表示附加信息、异常或依赖项。

Operation

Instant

In Place

Rebuilds Table

Permits Concurrent DML

Only Modifies Metadata

Adding a column

Yes*

Yes

No*

Yes*

Yes

Dropping a column

Yes*

Yes

Yes

Yes

Yes

Renaming a column

Yes*

Yes

No

Yes*

Yes

Reordering columns

No

Yes

Yes

Yes

No

Setting a column default value

Yes

Yes

No

Yes

Yes

Changing the column data type

No

No

Yes

No

No

Extending ​​VARCHAR​​ column size

No

Yes

No

Yes

Yes

Dropping the column default value

Yes

Yes

No

Yes

Yes

Changing the auto-increment value

No

Yes

No

Yes

No*

Making a column ​​NULL​

No

Yes

Yes*

Yes

No

Making a column ​​NOT NULL​

No

Yes*

Yes*

Yes

No

Modifying the definition of an ​​ENUM​​​ or ​​SET​​ column

Yes

Yes

No

Yes

Yes

三、语法和使用说明

1、添加列

登录后复制
ALTER TABLE tbl_name ADD COLUMN column_name column_definition, ALGORITHM=INSTANT;

INSTANT是MySQL8.0.12和INPLACE之后的默认算法。

当 INSTANT算法用于添加列时,以下限制适用:
1、添加列不能与ALTER TABLE不支持的其他操作在同一语句中组合ALGORITHM=INSTANT。
2、在MySQL 8.0.29之前,一列只能作为表的最后一列添加。不支持将列添加到其他列中的任何其他位置。从MySQL 8.0.29开始,可以将即时
添加的列添加到表中的任何位置。
3、不能将列添加到使用ROW_FORMAT=COMPRESSED的表、具有FULLTEXT索引的表、驻留在数据字典表空间中的表或临时表。临时表仅支持
ALGORITHM=COPY.
4、在MySQL 8.0.29之前,添加列时不会评估行大小限制。但是,在插入和更新表中的行的DML操作期间会检查行大小限制。从8.0.29开始,
添加列时会检查行大小限制。如果超出限制,则会报告以下错误消息:
"ERROR 4092 (HY000): Column can't be added with ALGORITHM=INSTANT as after this max possible row size crosses max permissible row size.
Try ALGORITHM=INPLACE/COPY."

可以在同一 ALTER TABLE语句中添加多个列。例如:
ALTER TABLE t1 ADD COLUMN c2 INT, ADD COLUMN c3 INT, ALGORITHM=INSTANT;

ALTER TABLE ... ALGORITHM=INSTANT在每次添加一或多列、删除一或多列或在同一操作中添加和删除一或多列的操作之后,都会创建一个新
的行版本 。该INFORMATION_SCHEMA.INNODB_TABLES.TOTAL_ROW_VERSIONS列跟踪表的行版本数。每次立即添加或删除列时,该值都会增加
。初始值为 0。
mysql> SELECT NAME, TOTAL_ROW_VERSIONS FROM INFORMATION_SCHEMA.INNODB_TABLES
WHERE NAME LIKE 'test/t1';

当通过表重建ALTER TABLE 或OPTIMIZE TABLE 操作重建具有即时添加或删除列的表时,该TOTAL_ROW_VERSIONS值重置为 0。允许的最大
行版本数为 64,因为每个行版本都需要额外的空间用于表元数据。当达到行版本限制时,ADD COLUMN or DROP COLUMN
using ALGORITHM=INSTANT被拒绝,并显示一条错误消息,建议使用 COPY or INPLACE 算法重建表。
'ERROR 4080 (HY000): Maximum row versions reached for table test/t1. No more columns can be added or dropped instantly. Please use COPY/INPLACE.'

2、删除一列

登录后复制
ALTER TABLE tbl_name DROP COLUMN column_name, ALGORITHM=INSTANT;
当 INSTANT算法用于删除列时,以下限制适用:
1、删除列不能与ALTER TABLE不支持的其他操作在同一语句中组合ALGORITHM=INSTANT。
2、不能从使用 ROW_FORMAT=COMPRESSED的表、具有 FULLTEXT索引的表、驻留在数据字典表空间中的表或临时表中删除列。临时表仅支持
ALGORITHM=COPY.

ALTER TABLE同一语句中可以删除多个列;例如:
ALTER TABLE t1 DROP COLUMN c4, DROP COLUMN c5, ALGORITHM=INSTANT;
每次使用 添加或删除列时ALGORITHM=INSTANT,都会创建一个新的行版本。该INFORMATION_SCHEMA.INNODB_TABLES.TOTAL_ROW_VERSIONS
列跟踪表的行版本数。每次立即添加或删除列时,该值都会增加。初始值为 0。

3、重命名列

登录后复制
ALTER TABLE tbl CHANGE old_col_name new_col_name data_type, ALGORITHM=INSTANT, LOCK=NONE;
MySQL8.0.28中添加了ALGORITHM=INSTANT对重命名列的支持。早期的MySQL服务器版本仅支持ALGORITHM=INPLACE or ALGORITHM=COPY命名列。
要允许并发 DML,请保持相同的数据类型并仅更改列名。
当您保持相同的数据类型和[NOT] NULL属性时,只需更改列名,就可以始终在线执行操作。
仅允许重命名从另一个表引用的列ALGORITHM=INPLACE。如果您使用ALGORITHM=INSTANTor ALGORITHM=COPY或其他操作使用这些算法的条件
,则 ALTER TABLE语句将失败。
ALGORITHM=INSTANT支持重命名虚拟列;ALGORITHM=INPLACE不支持。
ALGORITHM=INSTANT和ALGORITHM=INPLACE不支持在同一语句中添加或删除虚拟列时重命名列。在这种情况下仅ALGORITHM=COPY支持。

4、更改列数据类型

登录后复制
ALTER TABLE tbl_name CHANGE c1 c1 BIGINT, ALGORITHM=COPY;
仅支持更改列数据类型 ALGORITHM=COPY。

5、扩展​​VARCHAR​​列大小

登录后复制
ALTER TABLE tbl_name CHANGE COLUMN c1 c1 VARCHAR(255), ALGORITHM=INPLACE, LOCK=NONE;
列所需的长度字节数VARCHAR必须保持不变。对于VARCHAR大小为0到255字节的列,需要一个长度字节来对值进行编码。对于VARCHAR大小为
256 字节或更大的列,需要两个长度字节。因此,INPLACE ALTER TABLE仅支持将VARCHAR列大小从0字节增加到255字节,或从256字节增
加到更大的大小。INPLACE ALTER TABLE不支持增加VARCHAR列从小于256字节到大小等于或大于256字节。在这种情况下,所需的长度字节
数从1变为2,仅表拷贝 ( ALGORITHM=COPY) 支持。例如,尝试VARCHAR使用就地将单字节字符集的列大小从VARCHAR(255)更改为
VARCHAR(256) 会ALTER TABLE返回此错误:
ALTER TABLE tbl_name ALGORITHM=INPLACE, CHANGE COLUMN c1 c1 VARCHAR(256);
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

不支持VARCHAR使用就地减小大小。ALTER TABLE减小VARCHAR大小需要使用ALGORITHM=COPY

6、设置列默认值

登录后复制
ALTER TABLE tbl_name ALTER COLUMN col SET DEFAULT literal, ALGORITHM=INSTANT;
仅修改表元数据。默认列值存储在数据字典中。
  • 1.
  • 2.

7、删除列默认值

登录后复制
ALTER TABLE tbl ALTER COLUMN col DROP DEFAULT, ALGORITHM=INSTANT;
  • 1.

8、更改自动增量值

登录后复制
ALTER TABLE table AUTO_INCREMENT=next_value, ALGORITHM=INPLACE, LOCK=NONE;
修改存储在内存中的值,而不是数据文件。
在使用复制或分片的分布式系统中,您有时会将表的自动增量计数器重置为特定值。插入到表中的下一行使用其自动增量列的指定值。您也可
以在数据仓库环境中使用此技术,在该环境中,您会定期清空所有表并重新加载它们,然后从 1 重新启动自动递增序列。

9、创建NULL列

登录后复制
ALTER TABLE tbl_name MODIFY COLUMN column_name data_type NULL, ALGORITHM=INPLACE, LOCK=NONE;
就地重建表。数据被大量重组,使其成为一项昂贵的操作。
  • 1.
  • 2.

10、创建NOT NULL列

登录后复制
ALTER TABLE tbl_name MODIFY COLUMN column_name data_type NOT NULL, ALGORITHM=INPLACE, LOCK=NONE;
就地重建表。 STRICT_ALL_TABLES或者 STRICT_TRANS_TABLES SQL_MODE是操作成功所必需的。如果列包含 NULL 值,则操作失败。服务
器禁止对可能导致失去参照完整性的外键列进行更改。
  • 1.
  • 2.
  • 3.

11、修改​​ENUM​​​或 ​​SET​​列 的定义

登录后复制
CREATE TABLE t1 (c1 ENUM('a', 'b', 'c'));
ALTER TABLE t1 MODIFY COLUMN c1 ENUM('a', 'b', 'c', 'd'), ALGORITHM=INSTANT;
只要数据类型的存储大小不变,就可以立即或就地执行通过在有效成员值列表的末尾添加新枚举或集合成员来 修改ENUM或列的定义。
例如,将成员添加到具有8个成员的列会将每个值所需的存储空间从1个字节更改为2个字节;这需要一个表格副本。在列表中间添加成员会导致
对现有成员重新编号,这需要一个表拷贝。

12、外键操作

Operation

Instant

In Place

Rebuilds Table

Permits Concurrent DML

Only Modifies Metadata

Adding a foreign key constraint

No

Yes*

No

Yes

Yes

Dropping a foreign key constraint

No

Yes

No

Yes

Yes

四、补充

更多信息可以查看mysql官方文档

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

[转帖]mysql8 ALGORITHM=INSTANT 亿级数据秒速增加字段的更多相关文章

  1. MySQL使用pt-online-change-schema工具在线修改1.6亿级数据表结构

    摘  要:本文阐述了MySQL DDL 的问题现状.pt-online-schema-change的工作原理,并实际利用pt-online-schema-change工具在线修改生产环境下1.6亿级数 ...

  2. 通用技术 mysql 亿级数据优化

    通用技术 mysql 亿级数据优化 一定要正确设计索引 一定要避免SQL语句全表扫描,所以SQL一定要走索引(如:一切的 > < != 等等之类的写法都会导致全表扫描) 一定要避免 lim ...

  3. 不停机不停服务,MYSQL可以这样修改亿级数据表结构

    摘  要:本文阐述了MySQL DDL 的问题现状.pt-online-schema-change的工作原理,并实际利用pt-online-schema-change工具在线修改生产环境下1.6亿级数 ...

  4. 基于Mysql数据库亿级数据下的分库分表方案

    移动互联网时代,海量的用户数据每天都在产生,基于用户使用数据的用户行为分析等这样的分析,都需要依靠数据都统计和分析,当数据量小时,问题没有暴露出来,数据库方面的优化显得不太重要,一旦数据量越来越大时, ...

  5. Mongodb亿级数据量的性能测试

    进行了一下Mongodb亿级数据量的性能测试,分别测试如下几个项目:   (所有插入都是单线程进行,所有读取都是多线程进行) 1) 普通插入性能 (插入的数据每条大约在1KB左右) 2) 批量插入性能 ...

  6. 巧用redis位图存储亿级数据与访问 - 简书

    原文:巧用redis位图存储亿级数据与访问 - 简书 业务背景 现有一个业务需求,需要从一批很大的用户活跃数据(2亿+)中判断用户是否是活跃用户.由于此数据是基于用户的各种行为日志清洗才能得到,数据部 ...

  7. NEO4J亿级数据导入导出以及数据更新

    1.添加配置 apoc.export.file.enabled=true apoc.import.file.enabled=true dbms.directories.import=import db ...

  8. NEO4J亿级数据全文索引构建优化

    NEO4J亿级数据全文索引构建优化 一.数据量规模(亿级) 二.构建索引的方式 三.构建索引发生的异常 四.全文索引代码优化 1.Java.lang.OutOfMemoryError 2.访问数据库时 ...

  9. Mybatis 使用分页查询亿级数据 性能问题 DB使用ORACLE

    一般用到了mybatis框架分页就不用自己写了 直接用RowBounds对象就可以实现,但这个性能确实很低 今天我用到10w级得数据分页查询,到后面几页就迭代了很慢 用于记录 1.10万级数据如下 [ ...

  10. 挑战海量数据:基于Apache DolphinScheduler对千亿级数据应用实践

    点亮 ️ Star · 照亮开源之路 GitHub:https://github.com/apache/dolphinscheduler 精彩回顾 近期,初灵科技的大数据开发工程师钟霈合在社区活动的线 ...

随机推荐

  1. 【eBPF-03】进阶:BCC 框架中 BPF 映射的应用 v1.0

    eBPF 中实现内核态代码与用户态代码是可以实时通信的,这主要靠 BPF 映射 来实现. BPF 映射 是内核空间的一段内存,以 键值对 的方式存储.内核态程序可以直接访问 BPF 映射,用户态需要通 ...

  2. 使用Bot Framework建立你的第一个聊天机器人

    今天微软给我推送了一个邮件,大概是微软近期开发了很多人工智能相关的API,无意中看到了Bot Framework,就点进去看了看似乎还蛮有意思的.于是准备搭建一个环境试试. 第一步需要下载Bot Ap ...

  3. Go 自动补全gocode

    go语言自动补全代码,需要添加gocode的程序. 执行: go get github.com/nsf/gocode 一般来说,gocode的源码会在$GOPATH/src/github.com/ns ...

  4. 深入剖析 Linux Cgroups 子系统:资源精细管理

    本章主要演示以下 cgroups 下各个 subsystem 的作用. 根据难易程度,依次演示了 pids .cpu 和 memory 3 个 subsystem 的使用. 注:本文所有操作在 Ubu ...

  5. 如何使用loki查询日志中大于某一数字的值的日志

    简介 loki是一款轻量级的日志收集中间件,比elk体系占用的内存更小,采用go语言开发,可以利用grafana来查询loki中存储的日志,loki存储日志只对提前预设的标签做索引,所以日志存储空间占 ...

  6. Boost Your Strategy With The Content Marketing Tools

    Boost Your Strategy With The Content Marketing Tools In today's digital landscape, content marketing ...

  7. 【小白学YOLO】一文带你学YOLOv1 Testing

    摘要:本文将为初学者带详细分析如何进行YOLOv1 Testing的内容. YOLOv1 Testing 进入testing阶段,我们已经得到98个bounding box和confidence还有C ...

  8. GaussDB(DWS)字符串处理函数返回错误结果集排查

    摘要:在使用字符串处理函数时,有时会出现非预期结果的场景.在排除使用问题后,应该从encoding和数据本身开始排查. 本文分享自华为云社区<GaussDB(DWS)字符串处理函数返回错误结果集 ...

  9. Solon 开发进阶,三、常用配置说明

    Solon 开发进阶 一.插件扩展机制 二.体外扩展机制 三.常用配置说明 四.启动参数说明 五.全局异常订阅 应用主配置文件为: resources/app.yml( 或 app.propertie ...

  10. PPT 产品发布会PPT应该怎么样改

    PPT 毕业答辩PPT应该怎么样改 大图背景打底 刺眼 收集素材