目录
- DDL在线操作的场景
- DDL在线操作实现的思路
- 补充材料
- 附录
DDL在线操作的场景
最近在考虑KtSQL的索引实现,涉及到在线索引新建的思考。
如果要求系统在表创建时,就建立合理的索引格式,这是不符合实际情况的。所以索引建立存在运行后重建的需求。
索引的重建需要允许在线,对一个大规模的在线服务系统而言,停机是不允许的。
DDL在线操作实现的思路
约束
- 数据一致性
- 并发操作
- 性能
数据一致性
索引建立过程中,如果允许数据变更(DELETE、UPDATE、INSERT),会导致索引和数据的不一致性,
所以数据库的常规做法,是对需要建立索引的表进行锁定,只允许查询,直到索引建立完毕后,才允许解除锁定。
并发操作
既然要实现DDL在线操作,分布式的环境下,必须要考虑操作的并发性,最直接的做法自然是操作串行。
对一个表进行串行修改,可以用锁机制来实现。
不同于DML可以采用MVCC和统一事务服务做隔离,DDL会对分布节点都产生影响。所以DDL操作时,
需要获得操作目标的锁才能进行操作。
锁的粒度决定了运行的性能,如只需要锁定元数据而不需要对表进行锁定,但是也不必过度追求并发,
如对表先拷贝后全量处理,再锁定原表增量处理的做法,就是很消耗资源的做法。
元数据和表数据可以分离,好处是对元数据锁定并进行操作时,DML依然可以运行。
HBase对表进行操作的时候,会先disable table。这个过程会关闭掉所有region server的handler,
HBase对元数据操作的方式,影响到并发操作的具体实现。
MySQL采用分级锁机制对数据请求进行分级:
- LOCK=NONE: Permits concurrent queries and DML.
- LOCK=SHARED: Permits concurrent queries but blocks DML.
- LOCK=DEFAULT: Permits as much concurrency as possible (concurrent queries, DML, or both).
- LOCK=EXCLUSIVE: Blocks concurrent queries and DML.
性能
假如需要对10亿的数据进行索引创建,共100个节点,则单个节点需要处理对千万级数据进行处理。
同时要生成10亿的数据记录,引发的网络通信和读写操作都将是很大的消耗。
补充材料
MySQL DDL的锁级别
假设要进行DDL,必须要执行锁的话,哪一种锁级别是在保证逻辑正确性的前提下性能最好的?MySQL整理了一些可以参考的思路。
Operation | In-Place? | Copies Table? | Allows Concurrent DML? | Allows Concurrent Query? | Notes |
---|---|---|---|---|---|
添加索引 | Yes* | No* | Yes | Yes | 对全文索引的一些限制 |
删除索引 | Yes | No | Yes | Yes | 仅修改表的元数据 |
OPTIMIZE TABLE | Yes | Yes | Yes | Yes | 从 5.6.17开始使用ALGORITHM=INPLACE,当然如果指定了old_alter_table=1或mysqld启动带–skip-new则将还是COPY模式。如果表上有全文索引只支持COPY |
对一列设置默认值 | Yes | No | Yes | Yes | 仅修改表的元数据 |
对一列修改auto-increment 的值 | Yes | No | Yes | Yes | 仅修改表的元数据 |
添加 foreign key constraint | Yes* | No* | Yes | Yes | 为了避免拷贝表,在约束创建时会禁用foreign_key_checks |
删除 foreign key constraint | Yes | No | Yes | Yes | foreign_key_checks 不影响 |
改变列名 | Yes* | No* | Yes* | Yes | 为了允许DML并发, 如果保持相同数据类型,仅改变列名 |
添加列 | Yes* | Yes* | Yes* | Yes | 尽管允许 ALGORITHM=INPLACE ,但数据大幅重组,所以它仍然是一项昂贵的操作。当添加列是auto-increment,不允许DML并发 |
删除列 | Yes | Yes* | Yes | Yes | 尽管允许 ALGORITHM=INPLACE ,但数据大幅重组,所以它仍然是一项昂贵的操作 |
修改列数据类型 | No | Yes* | No | Yes | 修改类型或添加长度,都会拷贝表,而且不允许更新操作 |
更改列顺序 | Yes | Yes | Yes | Yes | 尽管允许 ALGORITHM=INPLACE ,但数据大幅重组,所以它仍然是一项昂贵的操作 |
修改ROW_FORMAT和KEY_BLOCK_SIZE | Yes | Yes | Yes | Yes | 尽管允许 ALGORITHM=INPLACE ,但数据大幅重组,所以它仍然是一项昂贵的操作 |
设置列属性NULL或NOT NULL | Yes | Yes | Yes | Yes | 尽管允许 ALGORITHM=INPLACE ,但数据大幅重组,所以它仍然是一项昂贵的操作 |
添加主键 | Yes* | Yes | Yes | Yes | 尽管允许 ALGORITHM=INPLACE ,但数据大幅重组,所以它仍然是一项昂贵的操作。如果列定义必须转化NOT NULL,则不允许INPLACE |
删除并添加主键 | Yes | Yes | Yes | Yes | 在同一个 ALTER TABLE 语句删除就主键、添加新主键时,才允许inplace;数据大幅重组,所以它仍然是一项昂贵的操作。 |
删除主键 | No | Yes | No | Yes | 不允许并发DML,要拷贝表,而且如果没有在同一 ATLER TABLE 语句里同时添加主键则会收到限制 |
变更表字符集 | No | Yes | No | Yes | 如果新的字符集编码不同,重建表 |