X-Engine是阿里巴巴自研的存储引擎,作为阿里云 RDS MySQL 的一个可选引擎,除了主打高性能和低成本,还减少了不少惠及用户的新性能。本文将具体介绍 MySQL(X-Engine) 如何近乎刹时实现传统数据库须要数小时实现的DDL操作。
1.数据库DDL操作面临的问题
互联网业务倒退迅速,利用模式频繁更改是常态。相应地,数据库拜访模式和schema也随之变动。DDL(Data Definition Language)是SQL的一类,次要作用是创立和更改数据的schema信息,最常见的操作包含:加减列、更改列类型、加减索引等。相熟MySQL的同学都晓得,在8.0以前,尽管Online DDL不阻塞其它DML(Insert/Update/Delete)操作,但许多重要的DDL操作,如加列、减列等,仍旧须要期待数小时、甚至好几天工夫(根据数据量的大小)才会失效。更改列类型等操作甚至仍须要锁表执行,阻塞DML操作。
DDL操作运行工夫长,占用系统资源,须要额定的磁盘空间(建设长期表),影响零碎吞吐,并且一旦DDL过程中实例crash,复原工夫也会很久。以加列DDL为例,MySQL经验如下过程:
1.以新schema建设空表。2.拷贝数据到新表,并且将新加列的值赋为默认值,同时更新索引表。数据库承受到的DML操作被记录在临时文件。3.加exclusive lock,阻塞写操作,将临时文件记录的DML操作apply到新表。如果DML很多,这一阶段将破费较多工夫。4.删除旧表,将新表命名为旧表的名字。
显然,这个过程加锁工夫长,拷贝数据操作会占用系统资源和长期空间,并须要大量I/O。为了适应变动频繁的业务,不立刻更改存储层数据、能够疾速实现的DDL(咱们称之为Fast DDL)成为了一个必要feature。MySQL 8.0 减少了instant add column性能,能够在短时间内只批改table元信息,实现加列操作。遗憾的是,它还不反对其它类型的DDL。得益于阿里自研的存储引擎X-Engine存储了多版本Table Schema,每一行记录在引擎层就实现了解析,并且能够根据更新版本的schema实现格局转换,X-Engine因而可反对多种类型的Fast DDL。
2.业界Fast ddl实现计划
MySQL 8.0
record记录了列个数, instant add column操作只批改零碎表。
写操作:新格局的记录。
读操作:依据存储在零碎表中default value补齐新加列。
反对类型:
• Change index optionRename table
• Set/drop default
• Modify column when the table is empty
• Add/drop virtual columnsAdd columns
MariaDB10.3
整体实现计划与MySQL8.0相似,record记录了列个数,在leftmost leaf page中记录所有列的default值.
反对类型:
• Add column
• Drop column
• Extend VARCHAR maximum (Only if the physical format allows; not VARCHAR(255) to VARCHAR(256))
Aurora
产生ddl后,更新零碎表,新、旧版本的schema均要记录下来。而后播送该批改。之后承受DML申请,首先转换相干leaf page的所有记录,而后执行DML。
select申请会将旧版本的记录拼接成新版本记录。
反对类型
• only supports adding nullable columns, without default values
3.X-Engine多版本schema
顾名思义,Fast DDL指数据库可能在极短的工夫内实现用户收回的DDL指令并返回。之所以这么快,是因为只修零碎表里的元数据,不变更引擎层存储的数据。其实现的关键在于:元信息变更之后,内存、磁盘中的物理记录该如何解析。
Engine的架构采纳了LSM-Tree的思维,将新写入的数据以追加形式写入内存memtable,memtable到肯定大小后switch为immutable memtable,不再批改。而后逐步以固定大小extent的模式,flush到长久化存储中。当extent到肯定数量后,通过合并(Compaction)操作,将雷同Key的多个版本合并。为了让每行记录可解析,最直观简略的计划便是将元信息附着在记录下面。为了可能不依赖零碎表解析记录,X-Engine存储了较为具体的元数据,如果为每一行都附着一份,会占用大量的空间。为了大大减少存储老本,咱们保障每个memtable和extent外部的数据schema统一,并将schema信息存储在memtable和extent之上。
schema信息蕴含了诸如列个数、列类型、列长度、默认值等要害信息。利用这些信息,X-Engine能够在返回后果之前,实现列解析,并只需返回查问指标列的对应后果。上面给出了一个具体的例子,同一张表存在不同schema版本的extent时,如何返回后果。
4.X-Engine fast ddl实现
当 MySQL 接管到一条fast ddl语句时,更新相干零碎表及元数据,新版本的表构造随之失效,这时这条DDL语句就执行胜利啦!到当初为止X-Engine存储的信息没有产生任何变动。
读申请
当零碎接管到Select申请时,MySQL 会将申请自身,连同以后最新版本schema信息(称之为target schema)传递到X-Engine。X-Engine首先定位到记录的地位(某个memtable或extent),并取相应数据schema解析记录失去初步后果。接着,比照数据schema和target schema,对初步后果做适当填充、删减或批改失去最终后果返回。
X-Engine schema更新
Fast DDL命令执行胜利,新版本的schema失效,X-Engine还对此无感知。当接管到第一条针对该表的DML(Insert/Update/ Delete)请后,如果发现X-Engine的沉闷memtable的schema版本落后于最新版本,会触发switch memtable行为:解冻以后沉闷memtable,产生新沉闷memtable,将新schema赋予新沉闷memtable。为了保证数据的正确性,该操作会期待所有正在进行的写事务实现后再执行。
写申请
每个写事务可能波及到n(n>=1)个表。事务在提交时,须要在写入沉闷memtable之前判断:事务写入数据的schema版本是否与沉闷memtable的schema版本统一,如果不统一则应该报错退出,揭示用户重试。
Flush/Compaction
内存中memtable数量到肯定个数时会触发Flush操作,被选中memtable的数据以extent的模式写入磁盘,schema也随之由memtable传递到extent。Compaction操作会合并多个extent,如果参加同一工作的extent schema版本不统一,X-Engine会以其中最新版本为准,生成新extent。
总结
Fast DDL能够解决很多利用的痛点,加列、扩大列的罕用的操作不必再须要漫长的期待。技术上,X-Engine通过存储具体的多版本schema信息,不仅无需借助零碎表解析记录,而且能够轻易地实现不同版本schema之间的数据转换,进而能够反对丰盛的Fast DDL类型。