非易失性數據庫系統存儲與恢復方法

非易失性數據庫系統存儲與恢復方法

摘要

非易失性內存的出現從根本上改變了數據庫管理系統的內存和持久存儲的架構。這些新型NVM設備具有堪比DRAM的速度,但是寫到NVM設備後這些數據就具備了持久性。因爲現現有的數據庫管理系統基於內存是易失的這樣的條件下,所以並不能充分利用這項技術。通過NVM,傳統數據庫管理系統的很多部件都將變得不再必要,並且會降低數據庫的性能。

爲了更好的理解這些問題,基於不同存儲管理架構下我們實現了三種引擎,並對其進行測試:(1)本地更新;(2)copy on write update;(3)基於日誌的更新。針對這三種情況,提出了適配NVM的變種,以充分利用NVM的持久性和字節尋址特性。實驗表明這些存儲架構可以提升5.5倍的性能並減少磨損量2倍以上。NVM適配的恢復協議,允許這些存儲引擎重啓時立即恢復。

引言

計算機的發展趨勢影響着OLTP應用的發展。數據庫管理系統時這些應用之中關鍵部分。優化數據庫性能非常重要。從存儲器上讀寫數據的快慢影響着數據庫性能。

數據庫管理系統也需要處理易失和非易失存儲設備之間的權衡利弊。爲了斷電後仍可以保存數據,數據庫系統需要將數據寫到非易失設備上,例如SSD或HDD。這些設備只支持以塊爲單位的慢速批量傳輸。和非易失設備不同,數據庫管理系統可快速從易失的DRAM上讀寫數據,但是一旦斷電,這些數據就會丟失。

另外,有一些固有的物理限制阻止DRAM容量擴展超出今天的水平。即使預留數據不經常使用,也需要階段性將他刷寫,所以使用大量DRAM時也會消耗大量電量。研究表明,DRAM消耗的電量佔整個server消耗的40%。

雖然基於flash的SSD具有更大的存儲容量,比DRAM消耗的電量更少,但是他還有其他問題。例如,SSD比DRAM速度更慢,僅支持基於block的訪問。這就意味着,即使僅僅更新了一個字節的數據也需要將整個block(通常是4K)刷寫下去。對於OLTP系統進行大量小規模寫的場景來說,這是有問題的。因爲這些設備每個地址只支持有限次數的寫。減小SSD的尺寸同樣會減小他的可靠性並增加干擾效應。電池支持的DRAM緩存等“權益之計”解決方案有助於緩解性能差異,但不能解決這些其他問題。

非易失性內存提供了兩種存儲介質。NVM是一類技術的統稱:相變內存、憶阻器、STT-MRAM等。表1比較了NVM和其他存儲技術的特性比較。

然而,如何在數據庫管理系統裏面充分利用這項新技術還不明朗。NVM幾方面特性使得現有的數據庫管理系統架構不再適合他們。例如面向磁盤的數據庫管理系統:Oracle、DB2、MySQL都是基於塊設備的管理系統。這些系統在內存中維護tuples的blocks,並最大化順序讀寫。面向內存的數據庫管理系統,例如VoltDB、MemSQL,通過某些部件克服DRAM的易失興。這些部件面對字節尋址並快速隨機讀寫的NVM來說,不再是必要的。

本文針對單NVM存儲架構,評估了不同OLTP數據庫管理系統的存儲和恢復方法。完成三種存儲引擎架構:基於日誌的本地更新;無日誌的copy-on-write更新;基於日誌的更新。然後對此三種方法進行優化以充分利用NVM。本文使用基於硬件的模擬器和易失性的CPU CACHE。分析表明,NVM優化方法性能提升了5.5倍並減小了一半NVM寫。同時,本地更新的NVM優化方法是最理想的方法,具有最小的開銷、設備磨損最小、允許幾乎瞬間重啓。

本文的工作使用單層的存儲架構。現在通過NV-DIMM替換DRAM成爲可能,並無需更改現有存儲架構即可運行NVM-only數據庫管理系統。本文的結構:section 2:討論NVM,爲什麼數據庫管理系統的存儲架構需要重新評估。Section 3:介紹測試的數據庫管理系統及本文開發的存儲引擎。Section 4:介紹基於NVM的優化方法。Section 5:測試及評估。Section 6:最近工作總結。

 

背景

下面綜述出現的NVM技術並討論本論文使用的硬件模擬平臺。

動機

   有兩類關係型數據庫架構:面向磁盤和麪向內存。前者例如IBM的R系統,內存中更新,將更新的記錄刷寫到磁盤;後者如IBM的IMS/VS,在內存中更新,通過硬盤保證持久性。保證所有改動都持久化的需求影響着這兩種架構的設計。依賴於隨機訪問的速度對數據存儲佈局進行優化。之前研究表明,OLTP工作負載的數據移動是相當大的。

NVM技術,例如phase change內存和memristors,通過字節尋址和低延遲的loads和stores指令避免這些轉換和傳輸的消耗。這就意味着NVM可用到內存數據庫中。但是和DRAM不同,寫到NVM就持久化了,因此重啓後或者崩潰重啓後不需重新加載數據庫就可直接訪問tuple。

NVM的優點顯而易見,在OLTP數據庫中充分利用他們非常重要。之前的研究表明,磁盤和內存數據庫使用NVM達到的性能差不多,由於記錄日誌的消耗。這是因爲,當前傳統數據庫都假設內存時易失的,因此需要將數據在持久設備上備份。因此從根本上了解不同存儲和恢復方法的特點。

本文部署了三個存儲引擎:in-place update引擎;copy-on-write update引擎和log-structured update引擎。每個引擎都支持主鍵和二級索引。

NVM-aware memory allocator

數據庫系統的NVM-aware memory allocator需要滿足兩個重要條件:第一,提供持久機制確保更改的數據到達NVM後是持久的。這就非常必要,因爲事務更改的數據在提交時,很可能人人在易失的CPU cache中。如果斷電,這些數據很可能會丟失。分配器需調用特定的API提供持久性機制。首先,通過CLFLUSH指令寫回cache line中數據,然後發起SFENCE指令確保來自CPU cache的數據持久。另外,這個數據很可能仍然在內存控制器中,斷電後也可能會丟失。從這裏開始,我們將上述的持久性機制稱爲sync原語。

第二個條件,提供一個命名機制,即使系統重啓後,指向內存位置的指針也是有效的。分配器需要確保映射內存後的虛擬地址不變。這樣,指向NVM的地址在操作系統或數據庫重啓後,仍然不變。將這個指針稱爲非易失指針。

NVM的分配器基於開源NVM開發庫libpmem。直接將NVM映射到地址空間,和文件系統API不同,訪問這樣的區域,不需要拷貝數據到用戶buffer。操作系統重啓後,分配器回收未持久的內存,重新存儲內部元數據到一個一致性狀態。恢復機制僅在操作系統重啓時啓用,數據庫重啓不需,因爲分配器會處理所有應用的內存。

測試的數據庫

In-place update引擎(InP)

該存儲引擎任何時候只有一個版本記錄。當事務更新一個字段值時直接覆蓋原有記錄。這是最有效的更新方法,存儲引擎更新記錄前不會拷貝一份記錄,只有更改字段變動,其他字段不動。基於VoltDB存儲引擎進行修改,這是一個面向內存的數據庫,不用維護免息磁盤數據庫的buffer pool等。InP存儲引擎使用STX B+tree作爲索引。

 

存儲:該存儲引擎架構如上圖所示。表的存儲區域分爲兩個pool,一個是固定大小的blocks,一個是可變長度的blocks。每個block包含一系列slot集。以固定大小的slots存儲表的元組。這就確保元組字節對齊,能夠很方便計算出記錄偏移。表大於8字節的字段存儲到變長slot中,slot的8字節地址存儲到tuple的字段域中。

這些block中的元組無序。對於每個表,數據庫維護這一個空閒元組slot鏈表,當一個事務刪除tuple時,被刪除元組的slot添加到這個pool中。當事務插入一個元組時,首先檢查表的pool是否有空閒slot。若pool爲空,分配固定導向的block。該存儲引擎同樣通過分配器幾口維護索引並將他們存儲到內存。

恢復:上次checkpoint後的事務數據未持久化,需要文件系統中的WAL進行恢復。WAL包括事務ID、表ID、記錄ID、新老記錄。

最知名的恢復協議是ARIES。存儲引擎週期性執行checkpoint,減少恢復延遲及日誌佔用的空間。我們實驗中,首先定位到checkpoint位置,然後回放WAL。我們不對索引進行WAL記錄,索引損壞時,恢復後可重建。

copy-on-write update引擎(CoW)

該存儲引擎更新前先拷貝記錄,更新拷貝的記錄。不需要記錄WAL。使用不同的director訪問數據庫中不同版本。最長見的爲IBM的R系統的shadow paging。數據庫維護這兩個查詢director:當前director和dirty director。當前director總是指向記錄最新版本,只對已提交的事務有影響。爲確保事務隔離性,存儲引擎維護一個master record,指向當前director。

 

    髒director指向活躍事務正在更改的記錄版本。Copy版本被更改成功後,更新髒director指向tuple的新版本。事務提交時,存儲引擎自動更新master record指向髒director。存儲引擎維護內部page cache確保內存中的熱數據頁。

CoW使用LMDB的copy-on-write B+tree完成shadow paging。

存儲:在文件系統中存儲directors。元組以HDD/SDD優化的格式存儲。每個database獨立存儲,master record在文件中固定位置。支持二級索引。

即使更新元組一個字段,也需要創建元組的備份。存儲引擎需要追蹤元組的不同版本,這樣才能夠回收不用版本記錄的空間。該存儲引擎具有很大的寫放大現象,增加了NVM設備的磨損,縮短了使用壽命。

恢復:如果master record更新前數據庫崩潰,重啓後髒director之前的更新不可見。因此該存儲引擎沒有恢復流程。當數據庫恢復到在線時,master record指向當前director確保一致性。異步回收髒director,只包含未提交事務的更新。

Log-structured update引擎(Log)

最後一個存儲引擎使用log-structured協議。這種方法來自log-structured文件系統,數據庫系統中稱爲log-structured merge(LSM)樹。LSM樹由一組runs數據集合組成。每個run包含有序元組集合。Runs駐留在易失性內存(MemTable)或持久設備(SSTables)。通過批量更新MemTable即週期性持久化減小寫放大。基於LevelDB進行修改。

 

存儲:該存儲引擎使用leveled LSM樹。MemTable中數據存儲在最上層,SSTable位於下一層。MemTable內容重啓後丟失。維護一個WAL日誌。首先在WAL中記錄更新,然後應用到MemTable。日誌中包含事務ID、表ID、元組ID、新舊值。爲減小IO消耗,批量組提交刷新日誌。

在寫密集負載中執行很高效,會帶來讀放大。

恢復:使用WAL恢復。先回放,然後刪除未提交的事務,將MemTable恢復到一致性狀態。

NVM-aware存儲引擎

前述的存儲引擎都是基於DRAM和HDD/SDD兩層存儲級。這些存儲設備具有不同的硬件限制和性能特性。非易失性存儲設備比DRAM有幾個數量級的讀寫延遲。數據庫以塊爲單位訪問非易失設備,而DRAM以字節訪問。順序和隨機寫性能差距比較大。

In-place update引擎(NVM-InP)

 

僅僅在WAL中記錄tuple的非易失指針。指針和指向的tuple都存儲在NVM。可以通過指針訪問tuple無需回放。將B+tree存儲到NVM,重啓後無需重建,立即可訪問。

存儲:表2概述了執行不同操作的步驟。引擎分別使用固定大小和可變長度的slot來存儲元組和非內聯字段(non-inlined fields)。要在系統重啓後回收由未提交事務插入的元組和非內聯字段的存儲空間,NVM-InP引擎在每個slot的頭部保存持久化狀態。slot可以處於三種狀態之一:未分配、已分配但未持久化以及分配並持久化。系統重新啓動後,分配但未持久化的slot將轉回未分配狀態。

NVM-InP引擎將WAL作爲非易失鏈表存儲。它使用原子寫的方式將新條目附加到鏈表中。每個條目都包含事務ID,要修改的表,元組ID以及指向更改操作的指針。這些更改包括用於插入操作的元組指針和用於非內聯字段上的更新操作的字段指針。在更新插槽狀態爲持久化之前,引擎會先持久化此條目。如果不能確保這個順序,那麼在系統重新啓動後引擎不能回收未提交事務所消耗的存儲空間,從而導致非易失性內存泄漏。在事務的所有更改都安全地保留後,引擎會截斷日誌。

引擎使用分配器接口維護非易失性B+樹實現主索引和二級索引。我們修改了STX B+樹庫,以便改變索引內部結構的所有操作都是原子的。例如,向B+樹節點添加條目時,不是按排序順序插入key,而是將條目附加到節點中的條目列表。

恢復:系統重新啓動後,已提交事務的效果會被持久化,因爲NVM-InP引擎在提交時立即保留事務所做的更改。因此,引擎在恢復期間不需要重放日誌。但未提交事務的更改可能存在於數據庫中,因爲內存控制器可以隨時刷新包含對NVM所做更改的高速緩存行。 NVM-InP引擎因此需要使用WAL來撤消這些事務。

爲了回滾(undo)插入操作,引擎使用WAL條目中記錄的指針釋放元組的存儲空間,然後刪除索引中與元組關聯的條目。在更新操作的情況下,引擎使用before image恢復元組的狀態。如果after image包含非內聯元組字段,則引擎釋放這些字段佔用的內存。對於刪除操作,它只需要更新索引以指向原始元組。爲了正確處理事務回滾和DBMS恢復,NVM-InP引擎只有在確定它們不再需要時才釋放由元組或非內聯字段佔用的存儲空間。由於此恢復協議不包括重做(redo)過程,因此NVM-InP引擎的恢復延遲較短,僅取決於未提交事務的數量。

 

copy-on-write update引擎(NVM-CoW)

 

NVM-CoW引擎直接持久化元組副本,並且僅在髒目錄中記錄非易失性元組指針。最後,它使用分配器提供的輕量級持久性機制來在copy-on-write B+樹中持久化更改。      

存儲:元組的存儲區域分佈在固定大小和可變長度數據的獨立池中。引擎保持兩個池中每個插槽的持久化狀態,類似於NVM-InP引擎。 NVM-CoW引擎使用分配器接口存儲非易失性copy-on-write  B+樹的當前和髒目錄。我們修改了LMDB中的B+樹,以更細的粒度處理修改以利用NVM的字節尋址能力。引擎使用分配器接口維護主記錄以支持有效的更新。當系統重新啓動時,引擎可以安全地使用主記錄訪問當前目錄,因爲該目錄保證處於一致狀態。這是因爲數據結構是隻追加(append-only)的,存儲在當前目錄中的數據永遠不會被覆蓋。

恢復:由於NVM-CoW引擎不會覆蓋提交的數據,因此它沒有恢復過程。當系統重新啓動時,它首先訪問主記錄(master record)以定位當前目錄。之後,它可以開始處理交易。故障時產生的髒目錄佔用的存儲空間由NVM分配器異步回收。

Log-structured update引擎(NVM-Log)

 

    日誌引擎批量緩存MemTable中的所有寫,以減少隨機訪問持久存儲[50,43]。但是,這種方法的好處對於僅包含NVM的存儲層次結構來說並不明顯,因爲順序訪問和隨機訪問之間的性能差距較小。我們在第3.3節中描述的原始日誌結構引擎中,週期性地將MemTable刷新到文件系統並壓縮SSTable以限制讀取放大會帶來顯著的開銷。與NVM-InP引擎類似,NVM-Log引擎會將事務執行的所有更改存儲在NVM上的WAL上。

     我們的NVM-Log引擎避免了MemTable和WAL中的數據重複,因爲它只記錄指向WAL中元組的非易失性指針。它不會將MemTable作爲SSTable刷新到文件系統,而只是將MemTable標記爲不可變,並啓動一個新的MemTable。這個不可變的MemTable在物理上以與可變MemTable以相同的方式存儲在NVM上。唯一的區別是引擎不會寫入不可變的MemTables。我們還修改了壓縮過程(compaction)以合併一組MemTable並生成一個新的更大的MemTable。 NVM-Log引擎使用NVM-aware恢復協議,其恢復延遲低於傳統恢復協議。

    存儲:NVM-Log引擎使用LSM來存儲數據庫。樹的每個級別都包含一個有序的數據。與日誌引擎相似,此引擎首先將所有由事務執行的更改存儲在作爲LSM樹最高級別的MemTable中。更改包括插入操作的元組內容,更新操作的更新字段和刪除操作的邏輯刪除標記。當MemTable的大小超過閾值時,NVM-Log引擎將其標記爲不可變(immutable),並啓動一個新的MemTable。我們修改了引擎用來限制讀取放大的定期壓縮邏輯,合併一組不可變的MemTable並創建一個新的MemTable。引擎爲每個不可變的MemTable構造一個布隆過濾器,以儘量減少不必要的索引查找。

      與Log引擎類似,NVM-Log引擎也維護一個WAL。 但WAL的目的不是重建MemTable,而是從MemTable中撤銷(undo)未提交事務的影響。表2顯示了NVM-Log引擎執行的操作的概況。與NVM-InP引擎類似,這個新引擎還是將WAL作爲非易失性鏈表條目存儲。當事務插入元組時,引擎首先將元組刷新到NVM,並將非易失性元組指針記錄在WAL條目中。然後它將持久化日誌條目並將該元組標記爲持久化狀態。最後,它在MemTable索引中添加一個條目。事務提交後,引擎會截斷相關日誌條目,因爲記錄在MemTable中的更改已經是持久化的。它的日誌記錄開銷比Log引擎低,因爲它記錄的數據較少並使用分配器接口維護WAL。引擎使用第4.1節中描述的非易失性B+樹作爲MemTable索引。因此,重新啓動時不需要重建索引。

     恢復:事務提交時,事務執行的所有更改都會保留在內存組件中。在恢復期間,NVM-Log引擎只需撤消MemTable上未提交事務的影響。同時它的恢復延遲低於Log引擎,因爲它不再需要重建MemTable。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章