本發(fā)明一般地涉及數(shù)據(jù)存儲系統(tǒng)和方法,更具體地涉及永久非易失性閃存數(shù)據(jù)庫存儲系統(tǒng)和方法。
背景技術:
永久半導體存儲器,諸如閃速存儲器(閃存,flash memory),的讀/寫性能正發(fā)展到一個點,它可能會很快替代一些應用中的內(nèi)部存儲器。預期隨著時間的推移非易失性閃速存儲器將變得跟DRAM一樣快。這會為閃速存儲器打開很多用于存儲系統(tǒng)諸如數(shù)據(jù)庫的獨特和不同的應用。然而,閃速存儲器可以被高效地用作數(shù)據(jù)庫之前,需要解決很多不同的問題,這需要用于編程語言編譯器諸如Java的不同的模型,以及極其不同的存儲系統(tǒng)架構解決方案。
傳統(tǒng)Java運行環(huán)境(JRE,Java runtime environment)目前沒有能力永久地存儲數(shù)據(jù)對象。所有的對象由構造函數(shù)在運行時創(chuàng)建并且存儲在易失性存儲器中(例如RAM)。這對閃速存儲器是不利的,因為需要利用完全不同的方式創(chuàng)建、刪除以及管理非易失性存儲器中的永久對象。創(chuàng)建易失性存儲器中的臨時對象的優(yōu)點在于,當應用關閉或被垃圾回收進程清除時,非引用對象可以被自動清除,這也會在運行時自動釋放內(nèi)存。這跟具有閃速存儲器的情形不同,該情形中對于刪除永久對象和釋放內(nèi)存來說確認動作是必須的。
另外,由于數(shù)據(jù)庫中對象的數(shù)量可以很大,因此存在如何基于查詢定義有效地發(fā)現(xiàn)并且檢索閃存陣列中的對象的問題。當使用閃速存儲器時需要解決的其它問題是如何確定對象的位置,從而可以對其引用,以及如何刪除存儲的對象和釋放內(nèi)存。尋找永久存儲器中的對象需要不同于易失性存儲器中使用的索引方法。確實,由于非易失性存儲器正在取代內(nèi)部存儲器,因此有必要重新思考傳統(tǒng)架構和技術。
傳統(tǒng)數(shù)據(jù)庫利用專用服務器產(chǎn)品將對象序列化成表結構,并且提供其它有益的能力以便于和加速查找,這些能力諸如事務模型、數(shù)據(jù)的一致視圖、查詢語言諸如SQL、更新單個數(shù)據(jù)域的能力,以及索引結構。這些能力涉及大量消耗會減慢軟件方案。伴隨的序列化/反序列化過程通常檢查各個集線器(hub)和緩存,這會在中央處理器(CPU)和內(nèi)存上導致很大的開銷、低效率和增加存儲成本。這對于閃存存儲是不合適的,閃存存儲中對象總是保存在存儲器中。需要用于管理對象的不同的事務模型以及檢索和刪除對象的不同解決方案。
技術實現(xiàn)要素:
需要提供基于永久閃速存儲器的新的以存儲器為中心的數(shù)據(jù)庫架構,其通過利用用于數(shù)據(jù)庫架構的閃速存儲器解決了前述和其它問題,并且這也是本發(fā)明期望的。
附圖說明
圖1是繪示了系統(tǒng)架構的方塊圖,該系統(tǒng)根據(jù)本發(fā)明的實施例提供全閃存編譯器和運行時環(huán)境。
圖2繪示了數(shù)據(jù)庫存儲的傳統(tǒng)方案。
圖3對比了根據(jù)本發(fā)明的全閃存數(shù)據(jù)庫方案和圖2中的傳統(tǒng)數(shù)據(jù)庫方案。
圖4繪示了用于索引永久對象的根據(jù)本發(fā)明的全閃存編譯器的操作。
圖5繪示了根據(jù)本發(fā)明的全閃存數(shù)據(jù)庫的索引結構的實施例。
圖6繪示了根據(jù)本發(fā)明的用于管理全閃存數(shù)據(jù)庫中的對象的處理的實施例。
圖7A-C繪示了根據(jù)本發(fā)明的用于刪除對象和壓縮存儲器的處理的實施例。
圖8A-C繪示了根據(jù)本發(fā)明的用于刪除全閃存數(shù)據(jù)庫中永久對象的不同的方案。
具體實施方式
本發(fā)明利用永久非易失性閃速存儲器提供新的和獨特的以存儲器為中心的數(shù)據(jù)庫架構,其將傳統(tǒng)數(shù)據(jù)庫有益的特性、靈活性和多功能性與閃速存儲器提供的速度、安全和方便結合在一起,同時獲取了相對于傳統(tǒng)存儲器改進的性能。根據(jù)本發(fā)明,提供了用于閃速存儲技術的新類型的編譯器和優(yōu)化的運行時(runtime)。本發(fā)明尤其非常適于與Java編程語言一起使用,以及用于數(shù)據(jù)庫應用,本文將對此進行描述。因此,在描述本發(fā)明的實施例時,說明書將使用與描述“全閃存Java編譯器”(all flash Java compiler,AFJC)、“全閃存Java運行環(huán)境”(all flash Java runtime environment,AFJRE)以及“全閃存數(shù)據(jù)庫”(all flash database,AFDB)有關的術語諸如“全閃存”(all flash)。然而,應當理解基于Java的存儲系統(tǒng)和方法只是繪示本發(fā)明的一個實例,本發(fā)明對于其他編程語言、環(huán)境和應用也有適應性。
圖1繪示了根據(jù)本發(fā)明的實施例的系統(tǒng)的架構,該系統(tǒng)提供用于根據(jù)本發(fā)明的實施例的全閃存存儲陣列的編譯器和運行時環(huán)境。如圖中所示,該系統(tǒng)包括連接至客戶端112的計算機系統(tǒng)(CPU)110、易失性存儲器114和非易失性存儲器116。該易失性存儲器和非易失性存儲器可以包括用于存儲控制程序的計算機可讀介質,該控制程序包括用于控制該計算機系統(tǒng)110的操作的可執(zhí)行指令。該非易失性存儲器可以包括形成數(shù)據(jù)庫的全閃存存儲陣列。編譯器120可以是編譯Java指令的Java編譯器,該Java指令是用于閃存永久存儲陣列而根據(jù)本發(fā)明定制的。該指令由計算機系統(tǒng)110執(zhí)行以創(chuàng)建Java運行時環(huán)境122。Java編譯器將稱為全閃存Java編譯器(AFJC),并且Java運行時環(huán)境將稱為全閃存Java運行時環(huán)境(AFJRE)。
如將要詳細描述的,本發(fā)明提供數(shù)據(jù)庫架構和永久數(shù)據(jù)模型,它們與傳統(tǒng)數(shù)據(jù)庫架構和模型是非常不同的。傳統(tǒng)數(shù)據(jù)庫被按照表進行組織。存儲和訪問這樣的傳統(tǒng)數(shù)據(jù)庫中的數(shù)據(jù)需要多個步驟,以在存儲器單元(memory locations)和各個頁面與存儲器緩存之間移動數(shù)據(jù)對象。反之,根據(jù)本發(fā)明,提供新的永久數(shù)據(jù)模型,其中將數(shù)據(jù)對象直接存儲于永久存儲器中,并且在永久存儲器中直接對其管理。這不同于所謂的對象數(shù)據(jù)庫,對象數(shù)據(jù)庫試圖通過將數(shù)據(jù)庫映射到不同的已知數(shù)據(jù)模型而使數(shù)據(jù)管理透明。將要被永久存儲的對象在創(chuàng)建時就被明確地限定和識別,并且可以明確地指明需要刪除的對象。另外,本發(fā)明提供事務管理模型,其中在單個事務中多個對象可以被自動地修改。如將要描述的,為了實施需要的新的實時行為,本發(fā)明的AFJC具體化該新的和不同的Java編譯器功能,該功能根據(jù)本發(fā)明的永久對象和事務管理模型而定制。
當基于提供給編譯器的指示而創(chuàng)建對象時,AFJC(編譯器)120可以決定將哪些對象存儲在易失性存儲器中,以及將哪些對象存儲在永久閃速非易失性存儲器中。有很多不同的方法可以用于提供該功能。根據(jù)第一種方法,可以缺省將所有的對象存儲在非易失性存儲器116中。當創(chuàng)建新的對象時,可以將它們自動存儲在閃存陣列中。該方法的優(yōu)點為,現(xiàn)有的應用可以受益于AFJRE而不需要重新編譯。由于利用該方法,臨時對象和永久對象之間沒有區(qū)別,可以在AFJRE中創(chuàng)建用于清理不需要的對象的新的垃圾回收器(GC),其具有新的堆實現(xiàn)方式(heap implementation)存儲閃存陣列116中的對象。
根據(jù)第二種優(yōu)選的方法,提供指示給編譯器,決定將哪些對象存儲在非易失性存儲器中,這被包含在對象定義中??梢岳肂ean注釋指明哪些對象應該存儲在閃存陣列中,以及哪些對象應該存儲在易失性存儲器中。可以將Bean注釋應用于類定義,它在使附加信息被包括進來方面是有利的,該附件信息諸如如何保存對象或對象的類,例如:
@flash-storage
Public Class MyObject{
String name;
Date date;
}
另外,可以將應用重新編譯,并且將bean注釋添加到程序中。該方法還影響AFJRE的其他方面。這些方面包括刪除對象和查找對象。
永久存儲器中的對象不會被自動刪除。缺省地,未被引用的對象可能被垃圾回收器刪除。為了避免對需要對象的刪除,可以采用垃圾回收方法,其中被引用的對象會免于被刪除。另外,如果不能發(fā)現(xiàn)永久對象,就不能使用該對象,優(yōu)選地,本發(fā)明執(zhí)行索引和查詢方案。索引將提供對對象的至少一個引用,這可以防止其被刪除??蛇x地,可以利用Java命令諸如object.delete()和object.finalize()控制垃圾回收器將特定對象從閃存陣列中刪除。如將要描述的,查詢方法可以利用由索引定義創(chuàng)建的索引查找存儲陣列中的對象。
圖2和圖3繪示和對比了從存儲器中的數(shù)據(jù)結構(圖2)中的傳統(tǒng)數(shù)據(jù)庫中檢索對象與訪問本發(fā)明(圖3)的AFDB中的永久對象的之間的區(qū)別。
圖2繪示了步驟的順序和伴隨的開銷(attendant overhead),以及發(fā)生在從存儲器中的數(shù)據(jù)結構中的傳統(tǒng)數(shù)據(jù)庫存儲陣列中檢索對象的低效率。應當理解,低效率的程度將依賴于數(shù)據(jù)庫的實際實現(xiàn)。參考圖2,構造函數(shù)可以在Java虛擬機(JVM)的棧212上創(chuàng)建引用,以從存儲陣列216訪問對象的數(shù)據(jù)頁214。數(shù)據(jù)庫客戶端218可以請求與來自數(shù)據(jù)庫服務器222的對象對應的數(shù)據(jù)頁。該數(shù)據(jù)庫服務器操作系統(tǒng)224可以從存儲設備檢索數(shù)據(jù)頁214,并且將這些頁存儲在存儲陣列的塊緩存230中。然后可以將這些頁搬運到操作系統(tǒng)224頁緩存和數(shù)據(jù)庫服務器222頁緩存中。Java虛擬機中的查詢引擎可以處理這些頁,并且創(chuàng)建結果集230,該結果集230被填充到該Java虛擬機的Java對象堆232中。
反之,根據(jù)本發(fā)明,如圖3所示,構造函數(shù)可以在Java虛擬機(JVM)310的棧312上創(chuàng)建引用,以從全閃存陣列316訪問永久對象314。該JVM310可以直接訪問對象314而不需要大量和各種類型的翻譯操作(translation operation),這在圖2中的傳統(tǒng)數(shù)據(jù)庫中是需要。因此,該操作不像傳統(tǒng)數(shù)據(jù)庫中那樣,不需要多個翻譯或發(fā)生附帶的低效率。訪問對象時,JVM310可以 使用或根據(jù)需要修改該對象。
Java提供用于在存儲器堆中查找對象的對象查詢語言(OQL)。本發(fā)明可以基于查詢定義利用該能力并結合索引系統(tǒng)定位全閃存陣列中的對象。本發(fā)明可以利用幾種方法定位對象。一種方式為全掃描整個閃存陣列并且測試所有對象。由于陣列中對象的數(shù)量可能很大,因此這種方法是低效的。因此,全掃描通常用于保守搜索(sparingly search)或優(yōu)選地只用于一次性搜索。并且,由于閃存陣列中沒有對象邊界,因此本發(fā)明可以創(chuàng)建構造函數(shù)以用注冊表注冊陣列上的對象,該注冊表使用對象的開始位置和其比特數(shù)量的長度。然后,全掃描會掃描整個注冊表以定位正確的對象。
本發(fā)明使用的第二種優(yōu)選的并且更有效的方法為創(chuàng)建一個或多個專用索引結構,諸如B-trees或倒置索引,以使對象被更容易地定位??梢岳脤ο蠖x上的Bean注釋識別對象屬性,可以利用該對象屬性創(chuàng)建該索引結構。可以將該索引結構存儲在存儲陣列數(shù)據(jù)庫中,并且將其注冊到注冊表中,從而可以查找到它們。單個bean定義可以保持多個索引,并且產(chǎn)生用于各個索引的索引管理的多個對應的代碼塊。索引可以是單鍵、組合鍵或倒序索引,并且可以被同步地或異步地更新。單鍵索引可以定義在對象屬性層,而組合索引定義在對象層。圖4-6繪示了該方案的實施例。
參考圖4,索引定義可以被定義在Java bean代碼402中,并且被提供給本發(fā)明的全閃存編譯器404,該全閃存編譯器將讀取該注釋以創(chuàng)建索引管理字節(jié)碼406。該字節(jié)碼可以創(chuàng)建索引410、更新索引412、刪除索引414或執(zhí)行索引查找416。生成的碼可以維護關于碼源自哪個索引定義的信息,從而處理類定義和索引定義變化。因此,該索引管理字節(jié)碼可以存儲索引信息,該索引信息包括類名、類版本識別符和索引定義的組合。用于單鍵同步B-tree索引的bean注釋的例子為:
@flash-storage
Public Class MyObject{
int id;@flash-index(synchronous,btree)
String name;
Date date;
}
用于組合鍵同步索引的例子為:
@flash-storage
@flash-composite-index(synchronous,btree)[id,date]
Public Class MyObject{
int id;
String name;
Date date;
}
用于倒序異步索引的例子為:
@flash-storage
@flash-composite-
index(synchronous,
btree)[id,date]Public
Class MyObject{
int id;
String name;@flash-
index(asynchronous,
inverted)Date date;
}
索引定義的例子為:
″com.emc.ecd.MyObject″,123456,flash-composite-index(synchronous,btree)[id,date],IndexByteCode″com.emc.ecd.MyObject″,123456,flash-index(synchronous,btree)[id],IndexByteCode
類版本標示符由Java運行時基于類定義產(chǎn)生,并且是版本識別的(version aware)。可以將其用于快速檢測類在加載到AFJRE期間是否發(fā)生了變化。該AFJRE將創(chuàng)建索引結構并在運行時加載類時將該索引結構注冊進全閃存陣列。 該注冊過程只需要發(fā)生一次,并且被綁定到類版本識別符,通過該類版本識別符與索引注冊到一起。優(yōu)選地,在永久映射中的對象堆中管理索引結構以快速定位索引結構。圖5繪示了該過程以及產(chǎn)生的全閃存陣列中的索引結構。
如圖5所示,Java虛擬機500可以包括對象堆502和索引堆504。該對象堆和索引堆可以管理全閃存陣列510中的永久索引結構。該全閃存陣列可以具有用于存儲索引結構的索引定義結構512和514,分別用于索引以數(shù)據(jù)對象516和518為首的多個索引數(shù)據(jù)對象(IDOs)。該圖只繪示了兩個這樣的數(shù)據(jù)對象結構,但應當理解可以具有很多這樣的數(shù)據(jù)對象結構。
本發(fā)明提供創(chuàng)建、更新和刪除對象以及他們的相關索引的過程。當創(chuàng)建了對象時,AFJRE可以確定是否具有與該對象類定義相關的索引。如果具有,則也應當為新數(shù)據(jù)更新該索引。AFJRE可以從索引堆中查找合適的索引定義、發(fā)現(xiàn)對索引定義的引用并且更新永久索引數(shù)據(jù)結構。當修改了對象時,AFJRE將跟蹤bean中的變化,并且確定是否具有需要更新的相關索引。它將從索引堆中查找合適的索引定義、發(fā)現(xiàn)對索引數(shù)據(jù)對象的引用并且更新永久索引數(shù)據(jù)結構。當刪除對象時,AFJRE將確定需要更新的相關索引,并且將被刪除對象的索引條目刪除??梢岳貌檎曳椒ㄖ苯訖z測到這些索引。AFJRE可以查找索引堆中的索引定義、加載索引字節(jié)碼并且執(zhí)行用于這些索引的查找方法。
圖6繪示了根據(jù)本發(fā)明的用于創(chuàng)建、更新和刪除對象的過程的例子。類加載器602將在604從字節(jié)碼獲取索引定義,并且在606從索引堆獲取索引定義。在608該過程將判斷是否具有任何新的索引定義,并且在610如果發(fā)現(xiàn)新的索引定義,將在612鎖定該索引堆,在614將注冊該新的索引定義,并且在616解鎖該索引堆。在620該過程將查找被改變的索引定義。在622,如果有任何索引定義已改變了,則在624將該索引堆再次鎖定。在626可以放棄該索引,并且在628注冊被改變的索引定義。在630再次將索引堆解鎖。在632可以注冊用于重索引的后臺工作(background job)。
本發(fā)明采用事務模型用于管理對象,該事務模型不同于一般Java運行時環(huán) 境中的事務模型,在一般Java運行時環(huán)境中不需要事務管理,因為存儲器內(nèi)更新總是成功的或者產(chǎn)生異常。然而,本發(fā)明的AFJRE是不同的,并且采用了不同的事務模型。本發(fā)明提供兩種不同的模型,分別用于隱性事務和顯性事務。
如果AFJRE沒有檢測到顯性事務內(nèi)容,那么它會采用隱性模型,在隱性模型中bean上的域更新是原子的(atomic)。相同的或不同的bean上的多個更新不能保證事務一致性。這意味著,例如這樣的操作:
{
object.id=123
}
將是閃存陣列上的原子操作,但是操作:
{
object.id=123
object.name=″foo″
}
將不是原子的,并且在兩個更新之間可以被中斷,從而只有第一個更新是永久的。
在顯式事務模型中,事務是顯示地執(zhí)行的,例如:
{
AFTransaction.begin()
object.id=123
object.name=″foo″
AFTransaction.commit()
}
Java堆是存儲器單元的集合,其中由程序根據(jù)需要分配和釋放動態(tài)程序數(shù)據(jù)。Java虛擬機的堆存儲由運行的Java應用創(chuàng)建的所有對象。根據(jù)本發(fā)明的AFDB Java堆構造以實現(xiàn)用于需要快速定位的對象的瞬時數(shù)據(jù)(instance data),并且在方法區(qū)中提供對象的類數(shù)據(jù)的訪問,該對象的類數(shù)據(jù)被給予對對象的引用。優(yōu)選地,本發(fā)明具有利用AFDB的單個堆,并且優(yōu)選地,在具有 直接指針引用的堆的頂端實施Java方法區(qū)。當虛擬機需要用于新加載類的存儲器時,其可以從對象在的相同的AFDB堆占用存儲器??梢岳貌煌姆椒z測對象并回收存儲器空間。例如,可以刪除未被引用的對象。垃圾回收器釋放未被引用的對象所占據(jù)的存儲器,也可以用于查找并釋放(卸載)未被引用的類??梢栽谝资源鎯ζ髦袟5膬?nèi)部管理對象引用,并且對象引用可以指向AFDB堆中的對象。本發(fā)明可以查詢AFDB堆以基于指針引用檢索對象。
為了釋放存儲器,本發(fā)明還提供用于永久數(shù)據(jù)的不同的垃圾回收方案。永久數(shù)據(jù)上的垃圾回收只有在刪除對象操作的情況下是相關的。例如,刪除操作可以是啟動使用的對象管理器接口,諸如:ObjectManager.delete(Object object)。在大多數(shù)情況下,刪除操作本質上是事務性的。然而,在有些情形中這是不可能。例如,如果其他并發(fā)進程或應用使用了對象,那么就不希望刪除該對象。然而,在永久隊列中可以將其標記為刪除,并且后臺進程可以異步移除該對象。另外,一些對象可以被其它對象引用,對象刪除將打斷引用完整性。在一些情況中,本發(fā)明可以采用強制刪除來刪除對象,而不管對該對象的引用的存在。
圖7A-C繪示了利用垃圾回收器刪除對象以及刪除后壓縮存儲器以釋放存儲器的例子。參考圖7A,假設AFDB中的永久存儲器700的塊存儲了六個對象O1-O6,并且在702中將對象O5標記為刪除。如圖7B所示,垃圾回收(GC)之后,如虛線指示的702中的對象O5被刪除,并且如虛線所指示的,之前由對象O5占據(jù)的永久存儲器700中的單元704現(xiàn)在是空的。繼刪除對象O5之后,可以執(zhí)行存儲器壓縮操作以壓縮存儲器700。如圖7C所示,710中,壓縮可以移動對象06至存儲器單元704,該存儲器單元704之前由被刪除的對象O5占據(jù),從而釋放存儲器單元712,該存儲器單元712原先由對象O6占據(jù)。如所示的,這會將對象O1-O4和O6壓縮到存儲器700中連續(xù)的單元。
圖8A-C繪示了將對象指示為刪除的不同方式。一種刪除對象的方式為通過中斷引用。圖8A-B對此進行了繪示。參考圖8A,在802中,對象O5可以 引用804中的對象O2和806中的對象O3,如由810和812指示的。如圖8B所示的,分別中斷對對象O2和O3的引用810和812之后,802中的對象O5不再有引用,并且可以被垃圾回收進程刪除。
圖8C繪示了指示對象刪除的另一種方案。如所示的,820中的對象O5可以引用一對對象即822中的對象O2和832中的對象O3,如826和828所指示的。在下一個垃圾回收中可以將肯定地將O5標記為刪除,并且如830和832所示的可以將其此分別傳遞給對象O2和O3。在下一個垃圾回收中,從而可以將對象O5肯定地刪除。如果需要,可以執(zhí)行以上所述的存儲器壓縮。
從前述可以理解,本發(fā)明利用永久非易失性閃速存儲器提供用戶數(shù)據(jù)庫的新的并且不同的以存儲器為中心的架構,其利用了閃速存儲器的獨特特點和效率,同時解決了對靈活性、易于數(shù)據(jù)管理和性能的要求,這對于在事務性環(huán)境中采用的數(shù)據(jù)庫是很重要的。因此,基于該架構的全閃存數(shù)據(jù)庫提供了極為簡單和更有效的數(shù)據(jù)庫存儲方法。
雖然以上所述引用了本發(fā)明的特定實施例,但是應當理解在不背離本發(fā)明的原則的情況下可以修改這些實施例,本發(fā)明的范圍由隨附的權利要求限定。