1. 程式人生 > >TDSQL 全時態數據庫系統--核心技術

TDSQL 全時態數據庫系統--核心技術

[1] ODB ESS 需要 檢查 算法 批量 管理 oss

TDSQL 全時態數據庫系統--核心技術
本文大綱:

Design
全時態數據模型
研究動機
數據模型
數據模型示例
歷史態數據存儲
數據轉儲時機
存儲格式
存儲模式
轉儲效率
歷史態數據可見性判斷

Design

本節討論T-TDSQL的關鍵之處,即影響T-TDSQL架構的設計之處。一是新的數據模型—全時態數據模型,表達了T-TDSQL的雙時態語義,其中對於數據的事務時態,首次提出全態數據的概念,以刻畫數據的生命周期。二是對於新的數據模型,如何在基於關系模型的數據庫中實現存儲,全時態數據的存儲,使得具有全時態語義的數據有了計算的依據;本文提出的全時態數據模型的實現,以MySQL為載體。第三是全態數據的讀取,關鍵是歷史態數據的可見性判斷算法的實現,文獻對此進行了詳細的描述,本文對核心算法介紹。

全時態數據模型

本文采用了基於關系數據模型而設計的雙時態數據模型。其與普通的關系數據模型主要的區別在於以下兩點,一是數據具有狀態屬性,二是數據具有時態屬性。具有這兩種屬性的數據模型,稱為全時態數據模型。

數據模型

數據的狀態屬性,標識數據的生命周期軌跡。數據的生命周期分為三個階段,每個階段刻畫數據的不同狀態屬性,以標識數據的生命周期軌跡中所處的狀態。

  1. 當前態(Current State):數據項的最新版本的數據,是處於當前階段的數據。處於當前階段的數據的狀態,稱為當前態。

  2. 歷史態(Historical state):數據項在歷史上的一個狀態,其值是舊值,不是當前值。處於歷史階段的數據的狀態,稱為歷史態。一個數據項的歷史態,可以有多個,反映了數據的狀態變遷的過程。處於歷史態的數據,只能被讀取不能再被修改或刪除。

  3. 過渡態(Transitional State):不是數據項的最新的版本也不是歷史態版本,處於從當前態向歷史態轉變的過程中。處於過渡態的數據,稱為半衰數據。

這三個狀態,涵蓋了一個數據項的生命周期,合稱為數據全態(full-state),或稱為全態數據。在MVCC機制下,數據的三種狀態均存在;在非MVCC機制下,數據只存在歷史態和當前態。

  1. 當前態:MVCC或封鎖並發訪問控制機制下,事務提交後的數據的新值處於當前態。

  2. 歷史態:MVCC機制下,當前活躍事務列表中最小的事務之前的事務生成的數據,其狀態處於歷史態。在封鎖並發訪問控制機制下,事務提交後,提交前的數據的值變為歷史態的值,即數據項的舊值處於歷史態。

  3. 過渡態:MVCC機制下,被讀取的版本上尚有活躍事務(非最新相關事務)在使用,因最新相關事務修改了數據項的值,其最新值已經處於一個當前態,被讀取到的值相對當前態已經處於一個歷史狀態,故其數據狀態介於當前態和歷史態之間,所以稱為過渡態。

數據的雙時態屬性,分別為有效時間屬性、事務時間屬性。

有效時間屬性表示數據表示的對象在時間屬性上的情況。如Kate中學起止時間是2000-09-01到2003-07-30,而大學起止時間是2003-09-01到2007-07-30,這裏的時間就是有效時間。

事務時間屬性表示數據的某個狀態的時間發生時刻。數據具有其時態屬性,即在何時數據庫系統進行了什麽樣的操作。某項操作在數據庫系統內被封裝為事務,而事務具有原子性。因此,我們采用了事務標誌來標識一個數據的事務時態屬性。

從形式上看,有效時間屬性和事務時間屬性,在數據模型中用普通的用戶自定義字段進行表示,只是用特定的關鍵字加以描述,供數據庫引擎進行約束檢查和賦值。

但是,一個定義有或不定義有雙時態屬性的數據項,其生命周期中一定存在全態形態,只是其全態形態的形成是通過事務時間屬性和DML操作觸發的。

數據模型示例

例如:對於員工-薪水這一關系,我們可以建立對應的雙時態數據模型,如圖2所示。其中,有效時間中表達“至今有效”,用關鍵字NOW;事務時間中表達“尚未更改”,用關鍵字UC,(Until Changed)。之後,數據經歷如下操作:

  1. op1. 2011-02-01 00:00:00添加新賬戶(4, ‘Jimmy’, 100, 2010-01-01,NOW);

  2. op2. 2012-01-01 00:00:00更新Kim的余額為200;

  3. op3. 2013-01-01 00:00:00調整Kim的余額為300;

  4. op4. 2014-01-01 00:00:00 註銷賬戶John

圖2中的數據經過上述操作,結果變遷為圖3所示,圖3表示了上述操作完成後的時刻處於全時態的數據狀況和變遷過程相關操作。
技術分享圖片

圖2 初始的雙時態數據模型圖(用戶表)
技術分享圖片

圖3變遷的雙時態關系模型圖(歷史表)

歷史態數據存儲

MySQL/InnoDB,PostgreSQL等采用MVCC技術的關系型數據庫,對於多版本的管理方案也不盡相同。MySQL/InnoDB將歷史態版本的數據通過Undo Log在內存中保存。PostgreSQL將歷史態版本元組直接鏈接在最新版本元組後,因此元組的多個版本在同一個數據頁面上(跨頁情況存在)。MySQL/InnoDB通過Purge操作來對歷史態版本進行清理, PostgreSQL通過Vacuum來對歷史態數據進行清理。

主流數據庫(關系型和非關系型)不會保存歷史態數據,丟棄了有價值的歷史態數據。而歷史態數據的價值,可以分為五個方面,第五章針對全時態類應用價值進行了討論。

本節將基於MVCC技術,討論對歷史態數據進行存儲的方案。

數據轉儲時機

相對於只支持當前態數據獲取的數據庫系統而言(如Oracle、MySQL/InnoDB、PostgreSQL),對於歷史態數據的轉儲,需要考慮兩個問題:

  1. 何時數據會被丟失而需要進行轉儲?

  2. 歷史態數據應該用怎樣的數據結構保存下來?

在歷史態數據被定期清理時,是將歷史狀態的數據進行轉儲的最佳時機,此時數據庫系統已經不再需要對歷史態數據進行DML操作。

由於系統清理是一種批量操作,所以歷史態數據也是采用類似的批量轉儲策略。當數據清理線程/進程工作時,轉儲線程/進程收集歷史態數據,插入到已經定義好的歷史表結構中。如圖4所示,給出了在MySQL/InnoDB系統中,一種可行且有效的數據轉儲方式。原表中被刪除或修改的歷史態版本會轉儲到歷史表中,並在歷史表中對數據進行重新組織,從而保證高的讀取效率。

在圖4中,我們延用了3.1.2節中定義的例子,並多做一步操作op5.調整Kim的余額為400。從而展示了完成五步操作後全態數據的分布情況。元組“1,Kim,300”元組,假設還有並發事務在使用,因此為過渡態。圖中歷史態數據的轉儲,將會在歷史態數據在UndoLog中被清除時發生。Undo Log中的一條元組(Undo Rec)元組了對應一條元組的歷史版本,Purge操作會將需要清理的Undo Log讀入內存中,我們通過對Undo Rec的解析,將元組歷史版本重新以物理元組的形式組織起來,存入到歷史表中,從而做到歷史態數據的持久化存儲。

轉儲操作是一個原子操作,同時作為一個內部事務執行,確保轉儲操作語義正確。未被轉儲的歷史態數據受系統舊有的故障恢復機制保護,確保不丟失。被轉儲後的歷史態數據被持久化存儲。
技術分享圖片

圖4 基於MySQL/InnoDB實現的歷史態數據轉儲原理圖

存儲格式

全時態數據模型,提供了全態語義和時態語義。

全態語義和時態語義對應的列信息,由用戶在CREATE TABLE語句中指定。而元組的結構,如圖5所示,包括兩部分,一是系統列,二是用戶定義列。系統列中的事務標識(Trx_id)表示本條版本是哪個事務操作後產生的版本。全態語義和Trx_id客觀上表示了事務時態的語義,與表示有效時間的時態語義結合,使得全時態數據模型支持了雙時態時態數據庫的語義。

在用戶表上執行DML操作,需要為歷史態版本的全態和時態對應列信息賦值。

歷史態的數據,存儲到歷史表。歷史表的結構和用戶原表的結構相近,只多一個列用於表示版本生成時對應的DML操作類型,值為enum(Operation) = {更新,刪除,插入}={U,D,I }={3,2,1 }。

歷史表禁止DML 操作,保證歷史態數據的安全性。

從系統的角度看,歷史表中的數據,只允許進行脫機和聯機操作。
技術分享圖片

圖5 歷史表元組結構圖

存儲模式

根據用戶對歷史態數據的計算需求,在歷史表的定義中可以指定的歷史態數據的存儲模式,當歷史態數據轉儲到歷史表中時,按照存儲模式,把歷史態數據轉儲為行存格式或者列存格式。

行存格式與傳統的關系型數據庫沒有本質區別。

列存格式的數據,支持MySQL體系中Column Store數據格式。另外將支持Parquet、RCFile、ORCFile等列存格式。

轉儲效率

對於列存格式的存儲模式,提供內存式轉儲過渡區,用以緩沖行格式的待轉儲的歷史態數據。等到轉儲過渡區滿,利用壓縮技術重新組織行存格式為列存。如圖6所示。

轉儲過渡區由若幹個連續的內存BLOCK/PAGE組成,每個BLOCK/PAGE大小等同於數據庫系統初始化階段指定的BLOCK/PAGE大小。
技術分享圖片

圖6 轉儲過渡區原理圖


同一個數據項可存在多個歷史態的版本。

哪個歷史態的版本可以被某個快照差讀取,是由歷史態數據可見性判斷算法決定的。此算法是一種新算法,有別於諸如PostgreSQL、MySQL/InnoDB中的版本可見性判斷算法。之前的算法可以稱之為當前態數據可見性判斷算法,能讀出全態數據中的當前態和過渡態數據。

歷史態數據可見性判斷算法與當前態數據可見性判斷算法這兩個算法合稱為全態數據可見性判斷算法。

歷史態數據的可見性判斷,不再能夠依賴活躍事務鏈表,這是因為對於歷史上任何時刻,其對應的“當前活躍事務列表”因時間流逝而不能夠被獲取。所以歷史態數據的可見性判斷算法有別與當前態數據的可見性判斷算法。
技術分享圖片

圖7 歷史態版本可見性判斷示例圖
圖7給出了一個使用歷史態數據可見性判斷算法、利用歷史快照差讀,獲取歷史態數據的實例。S1和S2是兩個歷史快照,存儲了快照的創建時間和其他相關信息。基於算法1 [1],即可判斷一條元組版本在給出快照差中的可見性,並給出產生本條歷史態元組的操作。算法1輸入為兩個事務快照s_start和s_stop,以及一條歷史態的元組版本r_i,輸出為當前元組版本的可見性opT,0代表不可見,1代表該版本是插入操作產生的, 2代表該版本是更新操作產生的,3代表該版本是刪除操作產生的。

算法1 歷史態數據可見性判斷算法

1 function HISTORY_VISIBILITY_JUDGEMENT (r_i, s_start, s_stop) 2 opT = 0 3 if s.start.createTime<r_i.commitTime<s_stop.createTime then 4 if r_i.isDelete then 5 opT = 3 6 else 7 if r_i.prev() then 8 opT = 1 9 else 10 opT = 2 11 else 12 opT = 0 13 end if 14 end function

TDSQL 全時態數據庫系統--核心技術