X-Engine 如何實(shí)現(xiàn) Fast DDL
X-Engine是阿里巴巴自研的存儲(chǔ)引擎,作為阿里云 RDS MySQL 的一個(gè)可選引擎,除了主打高性能和低成本,還增加了不少惠及用戶(hù)的新功能。本文將詳細(xì)介紹 MySQL(X-Engine) 如何近乎瞬時(shí)完成傳統(tǒng)數(shù)據(jù)庫(kù)需要數(shù)小時(shí)完成的DDL操作。 ##1.數(shù)據(jù)庫(kù)DDL操作面臨的問(wèn)題 互聯(lián)網(wǎng)業(yè)務(wù)發(fā)展迅速,應(yīng)用模式頻繁更改是常態(tài)。相應(yīng)地,數(shù)據(jù)庫(kù)訪問(wèn)模式和schema也隨之變化。DDL(Data Definition Language)是SQL的一類(lèi),主要作用是創(chuàng)建和更改數(shù)據(jù)的schema信息,最常見(jiàn)的操作包括:加減列、更改列類(lèi)型、加減索引等。
熟悉MySQL的同學(xué)都知道,在8.0以前,雖然Online DDL不阻塞其它DML(Insert/Update/Delete)操作,但許多重要的DDL操作,如加列、減列等,仍舊需要等待數(shù)小時(shí)、甚至好幾天時(shí)間(依據(jù)數(shù)據(jù)量的大?。┎艜?huì)生效。更改列類(lèi)型等操作甚至仍需要鎖表執(zhí)行,阻塞DML操作。 DDL操作運(yùn)行時(shí)間長(zhǎng),占用系統(tǒng)資源,需要額外的磁盤(pán)空間(建立臨時(shí)表),影響系統(tǒng)吞吐,并且一旦DDL過(guò)程中實(shí)例crash,恢復(fù)時(shí)間也會(huì)很久。以加列DDL為例,MySQL經(jīng)歷如下過(guò)程: ```
1.以新schema建立空表。
2.拷貝數(shù)據(jù)到新表,并且將新加列的值賦為默認(rèn)值,同時(shí)更新索引表。數(shù)據(jù)庫(kù)接受到的DML操作被記錄在臨時(shí)文件。
3.加exclusive lock,阻塞寫(xiě)操作,將臨時(shí)文件記錄的DML操作apply到新表。如果DML很多,這一階段將花費(fèi)較多時(shí)間。
4.刪除舊表,將新表命名為舊表的名字。
``` 顯然,這個(gè)過(guò)程加鎖時(shí)間長(zhǎng),拷貝數(shù)據(jù)操作會(huì)占用系統(tǒng)資源和臨時(shí)空間,并需要大量I/O。為了適應(yīng)變化頻繁的業(yè)務(wù),不立即更改存儲(chǔ)層數(shù)據(jù)、可以快速完成的DDL(我們稱(chēng)之為Fast DDL)成為了一個(gè)必要feature。
MySQL 8.0 增加了instant add column功能,可以在短時(shí)間內(nèi)只修改table元信息,完成加列操作。遺憾的是,它還不支持其它類(lèi)型的DDL。得益于阿里自研的存儲(chǔ)引擎X-Engine存儲(chǔ)了多版本Table Schema,每一行記錄在引擎層就完成了解析,并且可以依據(jù)更新版本的schema實(shí)現(xiàn)格式轉(zhuǎn)換,X-Engine因此可支持多種類(lèi)型的Fast DDL。
2.業(yè)界Fast ddl實(shí)現(xiàn)方案 **MySQL 8.0** record記錄了列個(gè)數(shù), instant add column操作只修改系統(tǒng)表。 寫(xiě)操作:新格式的記錄。 讀操作:根據(jù)存儲(chǔ)在系統(tǒng)表中default value補(bǔ)齊新加列。 支持類(lèi)型: ? Change index optionRename table ? Set/drop default ? Modify column when the table is empty ? Add/drop virtual columnsAdd columns **MariaDB10.3** 整體實(shí)現(xiàn)方案與MySQL8.0類(lèi)似,record記錄了列個(gè)數(shù),在leftmost leaf page中記錄所有列的default值. 支持類(lèi)型: ? Add column ? Drop column ? Extend VARCHAR maximum (Only if the physical format allows; not VARCHAR(255) to VARCHAR(256))
Aurora** 發(fā)生ddl后,更新系統(tǒng)表,新、舊版本的schema均要記錄下來(lái)。然后廣播該修改。之后接受DML請(qǐng)求,首先轉(zhuǎn)換相關(guān)leaf page的所有記錄,然后執(zhí)行DML。 select請(qǐng)求會(huì)將舊版本的記錄拼接成新版本記錄。 支持類(lèi)型 ? only supports adding nullable columns, without default values ##3.X-Engine多版本schema 顧名思義,F(xiàn)ast DDL指數(shù)據(jù)庫(kù)能夠在極短的時(shí)間內(nèi)完成用戶(hù)發(fā)出的DDL指令并返回。之所以這么快,是因?yàn)橹恍尴到y(tǒng)表里的元數(shù)據(jù),不變更引擎層存儲(chǔ)的數(shù)據(jù)。其實(shí)現(xiàn)的關(guān)鍵在于:元信息變更之后,內(nèi)存、磁盤(pán)中的物理記錄該如何解析。 Engine的架構(gòu)采用了LSM-Tree的思想,將新寫(xiě)入的數(shù)據(jù)以追加方式寫(xiě)入內(nèi)存memtable,memtable到一定大小后switch為immutable memtable,不再修改。然后逐漸以固定大小extent的形式,flush到持久化存儲(chǔ)中。
當(dāng)extent到一定數(shù)量后,通過(guò)合并(Compaction)操作,將相同Key的多個(gè)版本合并。為了讓每行記錄可解析,最直觀簡(jiǎn)單的方案便是將元信息附著在記錄上面。為了能夠不依賴(lài)系統(tǒng)表解析記錄,X-Engine存儲(chǔ)了較為詳細(xì)的元數(shù)據(jù),如果為每一行都附著一份,會(huì)占用大量的空間。為了大大減少存儲(chǔ)成本,我們保證每個(gè)memtable和extent內(nèi)部的數(shù)據(jù)schema一致,并將schema信息存儲(chǔ)在memtable和extent之上。 schema信息包含了諸如列個(gè)數(shù)、列類(lèi)型、列長(zhǎng)度、默認(rèn)值等關(guān)鍵信息。利用這些信息,X-Engine可以在返回結(jié)果之前,完成列解析,并只需返回查詢(xún)目標(biāo)列的對(duì)應(yīng)結(jié)果。下面給出了一個(gè)具體的例子,同一張表存在不同schema版本的extent時(shí),如何返回結(jié)果。
4.X-Engine fast ddl實(shí)現(xiàn) 當(dāng) MySQL 接收到一條fast ddl語(yǔ)句時(shí),更新相關(guān)系統(tǒng)表及元數(shù)據(jù),新版本的表結(jié)構(gòu)隨之生效,這時(shí)這條DDL語(yǔ)句就執(zhí)行成功啦!到現(xiàn)在為止X-Engine存儲(chǔ)的信息沒(méi)有發(fā)生任何變化。 **讀請(qǐng)求** 當(dāng)系統(tǒng)接收到Select請(qǐng)求時(shí),MySQL 會(huì)將請(qǐng)求本身,連同當(dāng)前最新版本schema信息(稱(chēng)之為target schema)傳遞到X-Engine。X-Engine首先定位到記錄的位置(某個(gè)memtable或extent),并取相應(yīng)數(shù)據(jù)schema解析記錄得到初步結(jié)果。接著,對(duì)比數(shù)據(jù)schema和target schema,對(duì)初步結(jié)果做適當(dāng)填充、刪減或修改得到最終結(jié)果返回。 **X-Engine schema更新** Fast DDL命令執(zhí)行成功,新版本的schema生效,X-Engine還對(duì)此無(wú)感知。當(dāng)接收到第一條針對(duì)該表的DML(Insert/Update/ Delete)請(qǐng)后,如果發(fā)現(xiàn)X-Engine的活躍memtable的schema版本落后于最新版本,會(huì)觸發(fā)switch memtable行為:凍結(jié)當(dāng)前活躍memtable,產(chǎn)生新活躍memtable,將新schema賦予新活躍memtable。為了保證數(shù)據(jù)的正確性,該操作會(huì)等待所有正在進(jìn)行的寫(xiě)事務(wù)完成后再執(zhí)行。
寫(xiě)請(qǐng)求
每個(gè)寫(xiě)事務(wù)可能涉及到n(n>=1)個(gè)表。事務(wù)在提交時(shí),需要在寫(xiě)入活躍memtable之前判斷:事務(wù)寫(xiě)入數(shù)據(jù)的schema版本是否與活躍memtable的schema版本一致,如果不一致則應(yīng)該報(bào)錯(cuò)退出,提醒用戶(hù)重試。 **Flush/Compaction** 內(nèi)存中memtable數(shù)量到一定個(gè)數(shù)時(shí)會(huì)觸發(fā)Flush操作,被選中memtable的數(shù)據(jù)以extent的形式寫(xiě)入磁盤(pán),schema也隨之由memtable傳遞到extent。Compaction操作會(huì)合并多個(gè)extent,如果參與同一任務(wù)的extent schema版本不一致,X-Engine會(huì)以其中最新版本為準(zhǔn),生成新extent。
總結(jié) Fast DDL可以解決很多應(yīng)用的痛點(diǎn),加列、擴(kuò)展列的常用的操作不用再需要漫長(zhǎng)的等待。技術(shù)上,X-Engine通過(guò)存儲(chǔ)詳細(xì)的多版本schema信息,不僅無(wú)需借助系統(tǒng)表解析記錄,而且可以輕易地實(shí)現(xiàn)不同版本schema之間的數(shù)據(jù)轉(zhuǎn)換,進(jìn)而可以支持豐富的Fast DDL類(lèi)型。
聲明:免責(zé)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶(hù)自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),也不承認(rèn)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)本社區(qū)中有涉嫌抄襲的內(nèi)容,請(qǐng)發(fā)
送郵件至:operations@xinnet.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),本站將立刻刪除涉嫌侵權(quán)內(nèi)容。本站原創(chuàng)內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)
需注明出處:新網(wǎng)idc知識(shí)百科