天天看點

記憶體中OLTP(Hekaton)裡的事務日志記錄

在今天的文章裡,我想詳細讨論下記憶體中OLTP裡的事務日志如何寫入事務日志。我們都知道,對于你的記憶體優化表(Memory Optimized Tables),記憶體中OLTP提供你2個持久性(durability)選項:

  • SCHEMA_ONLY
  • SCHEMA_AND_DATA

今天我不想更多讨論SCHEMA_ONLY,因為使用這個選項,在事務日志裡沒有發生任何日志(SQL Server 重新開機後你的資料會丢失)。今天我們會專門講解下SCHEMA_AND_DATA選項的持久性。

使用SCHEMA_AND_DATA持久性選項,SQL Server必須記錄你的事務到事務日志,因為每個記憶體中OLTP事務必須總是持久的。這個和傳統基于硬碟表是一樣的。但是記憶體中OLTP裡寫入事務日志比傳統表更優化。記憶體中OLTP支援多個并發日志流(在SQL Server 2014裡目前未實作),記憶體中OLTP隻記錄發生的邏輯事務(logical transaction)。

邏輯事務是什麼意思呢?假設你有5個非聚集索引定義的聚集表。如果你往表裡插入1條記錄,SQL Server必須記錄插入到聚集索引,還有5個額外的插入非聚集索引。在你表上定義的非聚集索引越多,SQL Server需要的日志越多。而且SQL Server隻能和事務日志一樣快。

使用記憶體中OLTP事情就變了。記憶體中OLTP,SQL Server隻記錄在你事務裡發生的邏輯修改。SQL Server對在你哈希或範圍索引裡的修改不記錄。是以1條日志記錄隻描述發生的邏輯INSERT/UPDATE/DELETE語句。結果是,記憶體中OLTP寫入更少的資料到你的事務日志,是以你的事務可以更快的送出。

我們來驗證它!

我想用1個簡單的例子向你展示下,當你首先插入10000條記錄到傳統基于硬碟表(Disk Based Table),然後插入記憶體優化表(Memory Optimized Table),SQL Server會有多少的資料寫入你的事務日志。下列代碼建立1個簡單表,在while循環裡插入10000條記錄。然後我用sys.fn_dblog系統函數(未文檔公開)來看事務日志。 

1 -- Create a Disk Based table
 2 CREATE TABLE TestTable_DiskBased
 3 (
 4     Col1 INT NOT NULL PRIMARY KEY,
 5     Col2 VARCHAR(100) NOT NULL INDEX idx_Col2 NONCLUSTERED,
 6     Col3 VARCHAR(100) NOT NULL
 7 )
 8 GO
 9 
10 -- Insert 10000 records into the table
11 DECLARE @i INT = 0
12 
13 BEGIN TRANSACTION
14 WHILE (@i < 10000)
15 BEGIN
16     INSERT INTO TestTable_DiskBased VALUES (@i, @i, @i)
17 
18     SET @i += 1 
19 END
20 COMMIT
21 GO
22 
23 -- SQL Server logged more than 20000 log records, because we have 2 indexes
24 -- defined on the table (Clustered Index, Non-Clustered Index)
25 SELECT * FROM sys.fn_dblog(NULL, NULL)
26 WHERE PartitionId IN
27 (
28     SELECT partition_id FROM sys.partitions
29     WHERE object_id = OBJECT_ID('TestTable_DiskBased')
30 )
31 GO      
記憶體中OLTP(Hekaton)裡的事務日志記錄

從系統函數的輸出你可以看到,你有比20000多一點的日志記錄。這是正确的,因為我們在表上有2個索引定義(1個聚集索引,1個非聚集索引)。

現在我們來看下用記憶體優化表(Memory Optimized Table)日志記錄有啥改變。下列代碼展示了為記憶體中OLTP資料庫必備工作:我們隻加了1個新的記憶體優化檔案組(Memory Optimized File Group),給它加了個容器:

1 --Add MEMORY_OPTIMIZED_DATA filegroup to the database.
 2 ALTER DATABASE InMemoryOLTP
 3 ADD FILEGROUP InMemoryOLTPFileGroup CONTAINS MEMORY_OPTIMIZED_DATA
 4 GO
 5 
 6 USE InMemoryOLTP
 7 GO
 8 
 9 -- Add a new file to the previously created file group
10 ALTER DATABASE InMemoryOLTP ADD FILE
11 (
12     NAME = N'InMemoryOLTPContainer', 
13     FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\InMemoryOLTPContainer'
14 )
15 TO FILEGROUP [InMemoryOLTPFileGroup]
16 GO      

下一步我建立了1個新的記憶體優化表(Memory Optimized Table)。這裡我在哈希索引上選擇了16384的桶數來避免哈希碰撞(hash collisions)的可能。另外我在Col2和Col3列上建立了2個範圍索引(Range Indexes)。

1 -- Creates a Memory Optimized table
 2 CREATE TABLE TestTable_MemoryOptimized
 3 (
 4     Col1 INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 16384),
 5     Col2 VARCHAR(100) COLLATE Latin1_General_100_Bin2 NOT NULL INDEX idx_Col2,
 6     Col3 VARCHAR(100) COLLATE Latin1_General_100_Bin2 NOT NULL INDEX idx_Col3
 7 ) WITH
 8 (
 9     MEMORY_OPTIMIZED = ON, 
10     DURABILITY = SCHEMA_AND_DATA
11 )
12 GO      

在那個表上合計有3個索引(1個哈希索引(Hash Index)和2個範圍索引(Range Indexes))。當你往表裡插入10000條記錄,傳統表會生成近30000的日志記錄——每個索引裡每個插入1條日志。

1 -- Copy out the highest 'Current LSN'
 2 SELECT * FROM sys.fn_dblog(NULL, NULL)
 3 GO
 4 
 5 -- Insert 10000 records into the table
 6 DECLARE @i INT = 0
 7 
 8 BEGIN TRANSACTION
 9 WHILE (@i < 10000)
10 BEGIN
11     INSERT INTO TestTable_MemoryOptimized VALUES (@i, @i, @i)
12 
13     SET @i += 1 
14 END
15 COMMIT
16 GO
17 
18 -- Just a few log records!
19 SELECT * FROM sys.fn_dblog(NULL, NULL)
20 WHERE [Current LSN] > '0000002f:000001c9:0032' -- Highest LSN from above
21 GO      

但現在當你看事務日志時,你會看到10000條插入隻生成了很少日志記錄——這裡是17條!

記憶體中OLTP(Hekaton)裡的事務日志記錄

 魔法發生在LOP_HK日志記錄裡。在這個特定日志記錄裡,記憶體中OLTP捆綁了多個修改到你的記憶體優化表(Memory Optimized Table)。你也可以通過使用sys.fn_dblog_xtp系統函數分解LOP_HK日志記錄: 

1 -- Let's look into a LOP_HK log record
2 SELECT * FROM sys.fn_dblog_xtp(NULL, NULL)
3 WHERE [Current LSN] > '0000002f:000001c9:0032' AND Operation = 'LOP_HK'
4 GO      
記憶體中OLTP(Hekaton)裡的事務日志記錄

從圖中你可以看到,記憶體中OLTP隻生成了近10000條LOP_HK日志記錄——在這個表上發生的每個邏輯插入對應1條記錄。 

小結

記憶體中OLTP提供你驚豔的性能提升,因為它是基于全新原理,例如MVCC和Lock-Free Data Structrues。另外它隻生成少量事務日志記錄,因為隻有邏輯改變被記錄寫入事務日志。我希望這個文章已給你更好的了解:記憶體中OLTP如何提升你的事務日志吞吐量。

感謝關注!

參考文章:

https://www.sqlpassion.at/archive/2015/03/09/transaction-logging-memory-oltp-hekaton/

注:此文章為

WoodyTu

學習MS SQL技術,收集整理相關文檔撰寫,歡迎轉載,請在文章頁面明顯位置給出此文連結!

若您覺得這篇文章還不錯請點選下右下角的推薦,有了您的支援才能激發作者更大的寫作熱情,非常感謝!

繼續閱讀