mysql ddl
2019-11-05 本文已影响0人
Darui30
Online DDL算法
- INSTANT(MySQL 8.0.12)
- INPLACE
- COPY
关注点从如下5个维度
-
Instant: 此变更可以"立刻"完成
-
In Place: 此变更由InnoDB引擎独立完成, 不需要使用Redo log等, 可以节省开销
-
Rebuild Table: 此变更会重建聚簇索引, 一般情况下, 涉及到数据变更时才需要重建聚簇索引
-
Permits Concurrent DML: 此变更进行时, 是否允许其他DML变更同一张表. 此特性关系到变更是否会长时间阻塞业务
-
Only Modifies Metadata: 此变更是否只变更元信息, 不涉及数据变更
可见,日常关注点尽量是不要影响线上的DML操作,如果可以不去rebuild操作最好。
关于OnlineDDL分类
只说比较常见的场景
- 添加二级索引(较快,理论上只会在innodb引擎层创建二级索引,在支持dml同时,需要维护月份ddl期间数据变更日志,待变更完成后回放到新的二级索引中。但,如果表过大,ddl时间过长,其实还是会影响到dml的并发)
- 删除二级索引(巨快,只需要修改元数据信息)
- 添加列(巨慢,没办使用到inplace,只能是copy操作)
- 修改列名(巨快,只需要修改元数据信息)
- 修改列字段类型(巨慢,没办使用到inplace,只能是copy操作)
- 修改列字段大小(巨快,只需要修改元数据信息)
- 修改列注释/默认值(巨快,只需要修改元数据信息)
- 删除列(较慢,需要改动数据行,还需要维护DDL期间的数据变更日志)
- 修改列名/字段大小/字段类型/注释,加上AFTER、BEFORE(巨慢,无论之前表情怎么样)
详细信息可以看手册
8.0.12的福音(立刻加列)
"立刻加列" 之所以高效的原因是:
- 在执行 "立刻加列" 时,不变更数据行的结构
- 读取 "旧" 数据时,"伪造" 新增的列,使结果正确
- 写入 "新" 数据时,使用了新的数据格式(增加了 instant 标志位 和 "列数" 字段),以区分新旧数据
- 读取 "新" 数据时,可以如实读取数据
但是
- 当出现 与 "立刻加列" 操作不兼容 的 DDL 操作时,数据表需要进行 重建
限制
- 刻加列" 的加列位置只能在表的最后,而不能加在其他列之间
在元数据中,只记录了 数据行 应有多少列,而没有记录 这些列 应出现的位置。所以无法实现指定列的位置 - "立刻加列" 不能添加主键列
加列 不能涉及聚簇索引的变更,否则就变成了 "重建" 操作,不是 "立刻" 完成了 - "立刻加列"不支持压缩的表格式
按照 WL 的说法:"COMPRESSED is no need to supported"(没必要支持不怎么用的格式)
参考链接
8.0 Online DDL Operations
MySQL DDL为什么成本高?
[原理解析] MySQL 为表添加列 是怎么"立刻"完成的