資料持久化是還原的前提,沒有資料的持久化,就無法還原記憶體優化表的資料,SQL Server In-Memory OLTP的記憶體資料能夠持久化存儲,這意味着記憶體資料能夠在SQL Server執行個體重新開機之後自動還原。在建立持久化的記憶體優化表時,必須設定選項:memory_optimized=on,durability=schema_and_data。記憶體優化表的持久化由兩個程序實作:Checkpoint和事務日志記錄,在伺服器重新開機之後,SQL Server通過存儲在磁盤上的事務日志和Checkpoint資料,能夠将記憶體優化表還原到任意一個事務一緻性的時間點。Checkpoint程序用于将資料更新寫入CheckPoint檔案,縮短資料還原的時間;将資料更新寫入事務日志檔案實作事務的持久化存儲,由于任何已經送出的資料更新都被持久化存儲,是以,記憶體資料庫通過Checkpoint和事務日志,能夠将資料寫入到持久化儲存設備,實作資料持久化,并能通過已存儲的資料還原記憶體優化表。
一,資料持久化的特性
流(Stream)是資料的Bytes流,以Append-Only方式寫入資料,這意味着,流寫入檔案隻能在流的末尾寫入資料。記憶體優化表的Checkpoint流和事務日志流都是流寫入檔案,流寫入方式的特點是寫入速度極快,減少了持久化資料的時間延遲。SQL Server通過把記憶體優化表的Checkpoint資料流和事務日志流寫入Disk,實作資料的持久化存儲。
日志流是在執行資料行版本的更新(插入和删除)操作時,由已經送出的事務更新産生的Log Records,事務日志流有如下特性:
- 事務日志寫入到事務日志檔案(.ldf)中;
- 和硬碟表(Disk-based Table)不同的是,記憶體優化表的事務日志經過優化,減少日志記錄的數量,隻存儲已送出的事務日志,用于事務的redo操作,不存儲undo的事務日志;
- 在事務送出時,産生事務日志,隻記錄插入和删除的行版本事務;
- 不記錄記憶體優化表的Index Operation的事務日志,除了Columnstore Index的壓縮階段;所有的Index都在還原時重新建立;
Checkpoint資料流由三部分組成:
- Data Stream包含插入操作的行版本資料;
- Delta Stream包含删除操作的行版本資料;
- LOB流(Large Data Stream)包含建立ColumnStore Index時,對LOB Column進行壓縮的資料;
記憶體優化表資料存儲在一個單獨的FileGroup中,在該FileGroup下建立的File實際上是一個Directory或Container,用于存儲Checkpoint流檔案;Checkpoint流檔案在檔案尾端順序寫入新的資料;在SQL Server中,Checkpoint檔案以 FileStream方式存儲,由SQL Server負責管理檔案的建立,删除和歸并。
二,事務日志的優化
記憶體優化表産生的事務日志經過優化,減少了日志記錄的數量和寫入次數。SQL Server隻将最小數量的日志寫入到事務日志檔案(.ldf)中,這展現在,事務日志隻執行Redo操作,不記錄undo事務;SQL Server把一組事務日志合并,在一個大的Log Record中包含多條更新操作,減少了日志寫入的次數。
1,事務日志檔案隻能執行Redo操作,不記錄undo事務
SQL Server對于記憶體記憶體優化表,隻将已送出事務更新寫入事務日志檔案,這樣,行版本的插入和删除操作都被寫入到磁盤檔案中,用于執行事務的redo操作,還原資料庫。由于日志記錄在事務送出時産生,未送出的事務日志沒有不會産生日志記錄,事務日志檔案也不會記錄undo事務,這就減少日志記錄的數量。
2,合并事務日志,在一個Log Record中包含多個資料更新操作
對于記憶體優化表事務,SQL Server不使用預寫日志機制(WAL,Write-Ahead Logging),日志記錄隻在事務送出時産生。對于WAL,SQL Server在将資料更新寫入Disk之前,先将Log Record寫入到事務日志檔案;在Checkpoint事件發生時,SQL Server會将尚未送出的事務日志寫入到事務日志檔案中;對于記憶體優化表,未送出的日志記錄永遠不可能寫入到磁盤,這是對日志記錄的一個優化;此外,記憶體優化對多個資料更新分組,在一個log record中記錄多條資料更新操作,這樣做,既減少了事務日志的總體大小和管理開銷,也減少事務日志的寫入次數。
三,Checkpoint程序
對于硬碟表(Disk-Based Table),Checkpoint操作的作用是減少資料庫還原的時間,保持事務日志中活動事務盡可能少;對于持久化的記憶體優化表,Checkpoint程序的作用是使資料更新被持久化寫入到磁盤,這樣,在伺服器重新開機時,SQL Server能夠利用存儲在Disk上的資料還原記憶體優化表。在查詢處理的過程中,事務不會去讀取Disk上的資料,Disk上的資料隻有一個作用,就是當伺服器重新開機時,将資料填充到記憶體中,還原記憶體優化表。
Checkpoint程序的特點:
- 持續性(Continuous):Checkpoint 關聯的IO操作随着日志活動積累而持續增加;
- 流IO(Streaming I/O):Checkpoint檔案使用流寫入方式,将資料順序寫入到檔案的末尾;
Checkpoint程序同時作用在硬碟表和記憶體優化表上,執行Checkpoint操作的方式有兩種:
- 手動執行Checkpoint操作:在SSMS中顯式執行checkpoint指令,SQL Server同時對硬碟表(Disk-Based Table)和記憶體優化表(Memory-Optimized Table)執行Checkpoint操作;
- 自動執行Checkpoint操作:從上一次Checkpoint事件結束後,如果事務日志的Size增長大約1.5GB,那麼SQL Server執行一次Checkpoint操作;事務日志的增長用于記錄新的Log Records,在事務對硬碟表和記憶體優化表執行更新操作産生的日志記錄;有可能,Checkpoint事件完全是由硬碟表資料的更新觸發的;
四,Checkpoint 檔案
SQL Server将Checkpoint資料存儲在四種類型的檔案中,分别是Data檔案,Delta檔案,Large Object檔案和Root檔案,這些檔案存儲在Checkpoint檔案的Container中,這個Container實際上是一個包含Memory_Optimized_Data的FileGroup的"File"。在第一次建立記憶體優化表時,SQL Server預先建立16個不同大小的空閑檔案(Free Files),大小是2MB的N次方,最小8MB,最大1GB,這些檔案的初始State是PreCreated。當需要使用檔案時,SQL Server從Free Files集合中擷取一個大小适當的Free File,将檔案的狀态由PreCreated轉換為适當的State。如果檔案的State是PreCreated,檔案的類型是Free。
1,初始檔案的大小
在初始狀态下,SQL Server為每個檔案類型至少建立3個足夠大小的Free files,共12個Free Files,每個檔案類型的初始大小取決于跟伺服器的配置,不同檔案的初始大小如圖:

2,Data/Delta檔案對
Data 檔案 和 Delta 檔案是最主要的Checkpoint檔案,包含了對記憶體優化表執行操作的所有更新操作的資訊。由于它們總是成對出現,稱作data/delta檔案對,也稱作CFP(Checkpoint File Pair),CFP隻會在檔案末尾順序寫入新的資料,即以Append-Only方式寫入資料,唯一的差別是寫入的行版本資料不同:
- Data 檔案隻存儲資料行的插入版本,在執行Insert 和Update操作時,會産生插入版本資料;
- Delta檔案隻存儲資料行的插入版本,在執行Delete和Update操作,會産生删除版本資料;
Data檔案和Delta檔案都會覆寫一定的時間戳範圍,從begin timestamp開始的所有行版本資料都包含在相同的Data檔案和Delta檔案中,在還原階段,從Data檔案中讀取資料,同時,從Delta檔案讀取資料,用于從Data檔案中過濾資料行,避免将已經删除的行版本重新加載到記憶體中。由于data檔案和delta檔案是1:1對應的,資料還原的最小機關是data/delta檔案對,不同的data/delta檔案對能夠并發處理。
3,LOB檔案和Root檔案
Large Data 檔案用于存儲LOB Column的資料值,或者ColumnStore Index的行組(RowGroup)内容,如果沒有LOB column或 Columnstore Index,SQL Server仍然會預先建立Large Data檔案,但是,這些檔案将保持FREE狀态。
Root檔案用于追蹤Checkpoint事件,每當發生Checkpoint事件時,一個新的Active root 檔案将會被建立。
4,Checkpoint檔案的狀态
Checkpoint 檔案的5種狀态分别是:PRECREATED,UNDER CONSTRUCTION,ACTIVE,MERGE TARGET和WAITING FOR LOG TRUNCATION。SQL Server預先建立12個Free Files,初始狀态是PreCreated。在使用這些檔案時,SQL Server将檔案的狀态轉換為Under Construction 或 Merge Target,檔案狀态的轉換過程如下圖:
通過DMV:sys.dm_db_xtp_checkpoint_files (Transact-SQL) 檢視Checkpoint檔案的State和類型。
五,Checkpoint檔案的歸并和删除
每次Checkpoint操作發生時,Checkpoint檔案都會增加,然而,随着時間的積累,記憶體優化表插入越來越多的行版本,越來越多的行版本被删除,導緻Data 檔案和Delta檔案記錄的資料量越來越多,使得讀取Data/Delta檔案對的時間消耗越來越大,這會嚴重影響資料庫還原操作,增加還原的時間。
解決該問題的方案是把時間戳範圍相鄰的,未删除資料行比例低于指定門檻值的多個Checkpoint檔案歸并到一個新的Checkpoint檔案對中。例如,有兩個Data檔案,DF1和DF2,它們的timestamp範圍相鄰,并且未被删除的資料行比例低于指定門檻值,把這兩個檔案合并成一個新的data檔案,DF3,該檔案的時間戳範圍覆寫原始檔案DF1和DF2,是DF1和DF2時間戳範圍的并集;在做資料歸并時,核對資料檔案DF1和DF2對應的delta檔案,從DF1和DF2中删除所有被标記為Delted的行版本,使DF3中隻存儲Inserted的行版本資料,在歸并結束後,DF3對應的delta檔案是空的。
1,自動歸并(Merge)
Checkpoin檔案對歸并操作是自動進行的,SQL Server内部建立一個背景程序,周期性地檢查所有的Data/Delta檔案對,将能夠歸并的Checkpoint檔案對劃分到一個集合中,使每個集合包含兩個或多個時間戳範圍連續的data/delta檔案對,位于相同集合中的多個檔案對必須能夠存儲在單個128MB的Data檔案中,歸并的政策如下表所示:
如果兩個時間戳範圍相鄰的資料檔案60%是滿的(60% Full,40%的資料行是deleted的),那麼它們不會被Merge,每個Checkpoint檔案中40%的空間将不會被使用。是以,持久化的記憶體優化表占用的總磁盤空間,比記憶體優化資料實際占用的存儲空間要大。在最差的情況下,實際占用的磁盤空間是記憶體優化資料的兩倍。
2,自動垃圾回收(Garbage Collection)
一旦Mege操作完成,原始的Checkpoint檔案對将不再使用,轉換到 WAITING FOR LOG TRUNCATION 狀态,隻要相應的事務日志被截斷,那麼垃圾回收程序就開始執行清理操作,實體删除不再使用的Checkpoint檔案對。在一個Checkpoint檔案對删除之前,SQL Server必須保證這些檔案不再被使用;垃圾回收程序是自動執行的,不需要任何幹預,事務日志的截斷發生的時機是:
- 備份事務日志:進行事務日志備份時,将截斷事務日志檔案;
- 資料庫處于auto_truncate模式:事務日志檔案隻記錄活動事務的日志,一旦事務完成,将自動截斷;
六,記憶體優化表的還原
在SQL Server執行個體重新開機時,SQL Server 以并發執行的方式還原記憶體優化表和硬碟表資料。每一個data檔案存儲的是插入的行版本資料,但是插入的行版本資料受到delta檔案的過濾,每一個delta檔案中存儲不需要從對應的data檔案加載的資料行。SQL Server對每一個data/delta檔案對進行優化配置,使資料加載程序能夠在多個IO流(IO Steam)中并發執行,每一個IO流都能單獨處理一個data/delta檔案對,多個IO流同時加載資料,提高資料還原的速度。
每一個記憶體資料庫都僅有一個包含Memory_Optimized_Data的檔案組(FileGroup),在該FileGroup下建立的每一個File,叫做一個Container,主要用于存儲data/delta檔案對,SQL Server為每一個Container建立一個delta-map,映射每一個Data 檔案中被Delta 檔案過濾的資料,這樣,被删除的資料就不會重新插入到記憶體優化表中。還原操作是流并發的,在對Container下的所有Data/Delta檔案對進行流處理時,SQL Server将資料加載任務配置設定給所有的CPU核心,根據delta-map,并發式處理Data/Delta檔案對。
一旦Checkpoint 檔案加載完成,SQL Server開始讀取尾事務日志,從上一次Checkpoing結束的時間戳(timestamp)開始,重新執行事務日志中記錄的Insert和Delete操作,等到所有的事務日志重新執行完成,資料庫就還原到伺服器停機的時刻,或備份操作開始的時間。在SQL Server 2016中,事務日志的讀取和Redo操作是并發執行的,是以,資料和事務日志都是并發操作,資料還原的過程是非常快的。