在今天的文章裡,我想詳細讨論下記憶體中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

從系統函數的輸出你可以看到,你有比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條!
魔法發生在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隻生成了近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技術,收集整理相關文檔撰寫,歡迎轉載,請在文章頁面明顯位置給出此文連結!
若您覺得這篇文章還不錯請點選下右下角的推薦,有了您的支援才能激發作者更大的寫作熱情,非常感謝!