第一次接觸終極事務處理——Hekaton


在這篇文章里,我想給出如何與終極事務處理(Extreme Transaction Processing (XTP) )的第一次接觸,即大家熟知的Hakaton。如果你想對XTP有個很好的概況認識,我推薦Kalen Delaney寫的關於它的白皮書中文版本點此下載,另外微軟研究院也發布了題為“對於內存數據庫的高性能並發控制機制(High-Performance Concurrency Control Mechanisms for Main-Memory Databases)”的研究白皮書,點此下載

XTP明確為你指出:對於你的SQL Server數據庫,在后台是存儲在文件流(FILESTREAM) 文件組里。因此當你想要使用XTP,首先你要做的是,增加一個新的文件流(FILESTREAM) 文件組到你對應的數據庫。新的文件組也必須標上MEMORY_OPTIMIZED_DATA屬性。以下腳本請在64位系統里的SQL Server 2014里運行。

1 -- Create new database
2 CREATE DATABASE TestDatabase
3 GO
4 
5 --Add MEMORY_OPTIMIZED_DATA filegroup to the database.
6 ALTER DATABASE TestDatabase
7 ADD FILEGROUP XTPFileGroup CONTAINS MEMORY_OPTIMIZED_DATA

 點擊【數據庫屬性】【文件組】,可以看到【內存優化數據】。

 在你創建新FILESTREAM文件組后,你還需要添加一個新的文件到這個文件組。

1 -- Add a new file to the previous created file group
2 ALTER DATABASE TestDatabase ADD FILE
3 (
4    NAME = N'HekatonFile1',
5    FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\HekatonFile1'
6 )
7 TO FILEGROUP [XTPFileGroup]
8 GO

在我們已經准備好用於XTP的數據庫后,最后我們可以添加我們的內存優化表(Memory Optimized Table)——這個名字就是SQL Server所指的XTP表:

 看到這個截屏,估計你很期待一個非常酷的表創建向導,但事實上我們只看到一個T-SQL腳本模板——沒別啥東東。希望微軟對此在后續版本會有所改進……下面是創建一個XTP表的必需腳本:

 1 USE TestDatabase
 2 -- Let's create a new Memory Optimized Table
 3 CREATE TABLE TestTable
 4 (
 5    Col1 INT NOT NULL,
 6    Col2 VARCHAR(100) NOT NULL,
 7    Col3 VARCHAR(100) NOT NULL
 8    CONSTRAINT chk_PrimaryKey PRIMARY KEY NONCLUSTERED HASH (Col1) WITH (BUCKET_COUNT = 1024)
 9 ) WITH (MEMORY_OPTIMIZED = ON)
10 GO

哎呀,報錯了。因為俺們用的是中文版本的SQL Server 2014,排序規則是:Chinese_PRC_CI_AS

看來對中文字符的支持還不是很好,我們可以換用數據類型 nchar(n) 或 nvarchar(n)。

 1 USE TestDatabase
 2 -- Let's create a new Memory Optimized Table
 3 CREATE TABLE TestTable
 4 (
 5    Col1 INT NOT NULL,
 6    Col2 NVARCHAR(100) NOT NULL,
 7    Col3 NVARCHAR(100) NOT NULL
 8    CONSTRAINT chk_PrimaryKey PRIMARY KEY NONCLUSTERED HASH (Col1) WITH (BUCKET_COUNT = 1024)
 9 ) WITH (MEMORY_OPTIMIZED = ON)
10 GO

在XTP里額每個表都必須要有一個非聚集哈希索引(Non-Clustered Hash Index)的約束。聚集哈希索引(Clustered Hash Index)目前尚不支持。你還要用BUCKET_COUNT子句來指定桶數。最后你要為數據庫標上MEMORY_OPTIMIZED。恭喜您,你已經創建了您的第一個內存優化表——這個一點都不難!

使用這個新表非常簡單。我們來插入幾條記錄:

1 -- Let's insert a simple record into the new table
2 INSERT INTO TestTable (Col1, Col2, Col3) VALUES (1, 'Woody', 'Tu')
3 GO

但是XTP的真正威力是在處理並發用戶的時候,因為沒有鎖/阻塞/封鎖(Locking/Blocking/Latching)。連排它鎖(Exclusive Locks (X) )也米有了。平常當我們在“普通”表上運行INSERT語句時,在表上會有IX鎖,在數據頁,在記錄本身會有一個X鎖。但在XTP里,這些鎖全不見了。來看下面的查詢: 

 1 -- Make an insert in an explicit transaction
 2 BEGIN TRANSACTION
 3 
 4 INSERT INTO TestTable (Col1, Col2, Col3) VALUES (2, 'Smart', 'GZ')
 5 
 6 -- No IX, X locks anymore!
 7 SELECT * FROM sys.dm_tran_locks
 8 WHERE request_session_id = @@SPID
 9 
10 COMMIT
11 GO

sys.dm_tran_locks的輸出結果可以看到,只有在表本身有一個模式穩定鎖(Schema Stability Lock (Sch-S) ),但IX和X鎖都消失了——非常酷!

當你運行剛才的腳本不馬上提交事務:

1 BEGIN TRANSACTION
2 
3 INSERT INTO TestTable (Col1, Col2, Col3) VALUES (3, 'Cn', 'Blog')

你仍然可以從另外一個會話通過SELECT語句無鎖的獲得最新數據,在執行查詢之前,我們在工具欄點擊顯示實際的執行計划:

1 SELECT * FROM dbo.TestTable

 

SQL Server在執行計划里使用了Index Scan (NonClusteredHash) 運算符。

在XTP之前,這個行為在數據庫里只能通過啟用樂觀並發控制(Optimistic Concurrency)來建立——在SQL Server 2005后才引入了Read Committed Snapshot IsolationSnapshot Isolation

我們來試下UPDATE語句:

1 UPDATE TestTable SET Col2 = 'Test' WHERE Col1 = 1
2 GO

當我們看UPDATE執行計划時,除了Index Seek (NonClusteredHash)運算符,這里沒啥特別的地方。因此XTP能掃描和查找哈希索引(Hash Indexes)。我們來試下顯示事務里的UPDATE語句:

 1 -- Let's try the UPDATE statement in an explicit transaction
 2 BEGIN TRANSACTION
 3 
 4 UPDATE TestTable SET Col2 = 'Test' WHERE Col1 = 1
 5 
 6 SELECT * FROM sys.dm_tran_locks
 7 WHERE request_session_id = @@SPID
 8 
 9 COMMIT
10 GO

這一次,SQL Server給我們了下列錯誤信息:

因此當你使用顯示事務時,我們要提示SQL Server。但是WITH (SNAPSHOT)SNAPSHOT事務隔離級別(Transaction Isolation Level)不一樣,因為當我更改隔離級別為SNAPSHOT,並嘗試回滾事務時:

1 SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
2 BEGIN TRANSACTION
3 
4 UPDATE TestTable  SET Col2 = 'Test' WHERE Col1 = 1
5 
6 ROLLBACK 

我會收到如下的錯誤信息:

 

因此,我們給查詢本身加上查詢提示:

1 BEGIN TRANSACTION
2 
3 UPDATE TestTable WITH (SNAPSHOT) SET Col2 = 'Test' WHERE Col1 = 1
4 
5 SELECT * FROM sys.dm_tran_locks
6 WHERE request_session_id = @@SPID
7 
8 COMMIT
9 GO

現在事務已經提交,sys.dm_tran_locks 再一次只顯示了Sch-S鎖。下一步我想做的是嘗試並行執行2個UPDATE語句,但不提交第1個事務。因此我們在2個不同的會話執行下列語句,並確保2個事務都不提交。

1 BEGIN TRANSACTION
2 
3 UPDATE TestTable WITH (SNAPSHOT) SET Col2 = 'Test' WHERE Col1 = 1

沒有XTP,第2個事務會阻塞,因為X鎖正被第1個事務拿着:

很遺憾SQL Server在第2個會話里給我們下列的錯誤信息:

 

我們的執行進入更新沖突(Update Conflict),SQL Server回滾了第2個事務。我並沒有料到這點,但我需要對此仔細思考下。

在當前SQL Server 2014 CTP1版本里,XTP提供給你的另一個東西叫做 本機編譯的存儲過程(Natively Compiled Stored Procedures)

 

又一次,沒有向導,只有你要用到的T-SQL腳本模板。本機編譯(Native Compilation)意味這SQL Server在后台將整個存儲過程編譯至C/C++代碼——這個性能將會是卓越的,因為現在我們在SQL Server內部直接執行本機代碼(native code)。下面腳本展示了一個簡單的XTP存儲過程是啥樣的:

 1 CREATE PROCEDURE HekatonProcedure
 2 (
 3    @Param INT
 4 )
 5 WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
 6 AS
 7 BEGIN
 8    ATOMIC WITH
 9    (
10       TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english'
11    )
12 
13    INSERT INTO dbo.TestTable (Col1, Col2, Col3) VALUES (@param, N'Woody', N'Tu')
14 
15    SELECT Col1, Col2, Col3 FROM dbo.TestTable
16 END
17 GO

有幾個屬性必須要知道:

  • 存儲過程必須用SCHEMABINDINGEXECUTE AS來創建;
  • 存儲過程必須標記為NATIVE_COMPILATION
  • 你必須指定ATOMIC代碼塊,這里設置事務隔離級別和所用語言。

當你完成存儲過程創建后,你就可以執行它了:

1 EXEC HekatonProcedure 5
2 GO

因為現在你用的是本機代碼,那就沒有執行計划了!好好享受這執行速度……ALTER PROCEDURE也不支持了(沒意義,因為是本地生成代碼(native generated code)),意味如果你想修改這個存儲過程的話,你還不能再次DROPCREATE

這是我第一次安裝SQL Server 2014體驗XTP的簡短過程。更多的信息和內容,我定會在接下來的文章里和大家一起分享。請繼續關注!

參考文章:

https://www.sqlpassion.at/archive/2013/06/25/first-steps-with-extreme-transaction-processing-hekaton/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM