在這篇文章里,我想給出如何與終極事務(wù)處理(Extreme Transaction PRocessing (XTP))的第一次接觸,即大家熟知的Hakaton。如果你想對XTP有個很好的概況認識,我推薦Kalen Delaney寫的關(guān)于它的白皮書,中文版本點此下載,另外微軟研究院也發(fā)布了題為“對于內(nèi)存數(shù)據(jù)庫的高性能并發(fā)控制機制(High-Performance Concurrency Control Mechanisms for Main-Memory Databases)”的研究白皮書,點此下載。
XTP明確為你指出:對于你的SQL Server數(shù)據(jù)庫,在后臺是存儲在文件流(FILESTREAM) 文件組里。因此當你想要使用XTP,首先你要做的是,增加一個新的文件流(FILESTREAM)文件組到你對應(yīng)的數(shù)據(jù)庫。新的文件組也必須標上MEMORY_OPTIMIZED_DATA屬性。以下腳本請在64位系統(tǒng)里的SQL Server 2014里運行。
1 -- Create new database2 CREATE DATABASE TestDatabase3 GO4 5 --Add MEMORY_OPTIMIZED_DATA filegroup to the database.6 ALTER DATABASE TestDatabase7 ADD FILEGROUP XTPFileGroup CONTAINS MEMORY_OPTIMIZED_DATA
點擊【數(shù)據(jù)庫屬性】【文件組】,可以看到【內(nèi)存優(yōu)化數(shù)據(jù)】。
在你創(chuàng)建新FILESTREAM文件組后,你還需要添加一個新的文件到這個文件組。
1 -- Add a new file to the previous created file group2 ALTER DATABASE TestDatabase ADD FILE3 (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
在我們已經(jīng)準備好用于XTP的數(shù)據(jù)庫后,最后我們可以添加我們的內(nèi)存優(yōu)化表(Memory Optimized Table)——這個名字就是SQL Server所指的XTP表:
看到這個截屏,估計你很期待一個非常酷的表創(chuàng)建向?qū)В聦嵣衔覀冎豢吹揭粋€T-SQL腳本模板——沒別啥東東。希望微軟對此在后續(xù)版本會有所改進……下面是創(chuàng)建一個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,排序規(guī)則是:Chinese_PRC_CI_AS
看來對中文字符的支持還不是很好,我們可以換用數(shù)據(jù)類型 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子句來指定桶數(shù)。最后你要為數(shù)據(jù)庫標上MEMORY_OPTIMIZED。恭喜您,你已經(jīng)創(chuàng)建了您的第一個內(nèi)存優(yōu)化表——這個一點都不難!
使用這個新表非常簡單。我們來插入幾條記錄:
1 -- Let's insert a simple record into the new table2 INSERT INTO TestTable (Col1, Col2, Col3) VALUES (1, 'Woody', 'Tu')3 GO
但是XTP的真正威力是在處理并發(fā)用戶的時候,因為沒有鎖/阻塞/封鎖(Locking/Blocking/Latching)。連排它鎖(Exclusive Locks (X))也米有了。平常當我們在“普通”表上運行INSERT語句時,在表上會有IX鎖,在數(shù)據(jù)頁,在記錄本身會有一個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 COMMIT11 GO
從sys.dm_tran_locks的輸出結(jié)果可以看到,只有在表本身有一個模式穩(wěn)定鎖(Schema Stability Lock (Sch-S)),但IX和X鎖都消失了——非常酷!
當你運行剛才的腳本不馬上提交事務(wù):
1 BEGIN TRANSACTION2 3 INSERT INTO TestTable (Col1, Col2, Col3) VALUES (3, 'Cn', 'Blog')
你仍然可以從另外一個會話通過SELECT語句無鎖的獲得最新數(shù)據(jù),在執(zhí)行查詢之前,我們在工具欄點擊顯示實際的執(zhí)行計劃:
1 SELECT * FROM dbo.TestTable
SQL Server在執(zhí)行計劃里使用了Index Scan (NonClusteredHash) 運算符。
在XTP之前,這個行為在數(shù)據(jù)庫里只能通過啟用樂觀并發(fā)控制(Optimistic Concurrency)來建立——在SQL Server 2005后才引入了Read Committed Snapshot Isolation、Snapshot Isolation。
我們來試下UPDATE語句:
1 UPDATE TestTable SET Col2 = 'Test' WHERE Col1 = 12 GO
當我們看UPDATE執(zhí)行計劃時,除了Index Seek (NonClusteredHash)運算符,這里沒啥特別的地方。因此XTP能掃描和查找哈希索引(Hash Indexes)。我們來試下顯示事務(wù)里的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 COMMIT10 GO
這一次,SQL Server給我們了下列錯誤信息:
因此當你使用顯示事務(wù)時,我們要提示SQL Server。但是WITH (SNAPSHOT)和SNAPSHOT事務(wù)隔離級別(Transaction Isolation Level)不一樣,因為當我更改隔離級別為SNAPSHOT,并嘗試回滾事務(wù)時:
1 SET TRANSACTION ISOLATION LEVEL SNAPSHOT;2 BEGIN TRANSACTION3 4 UPDATE TestTable SET Col2 = 'Test' WHERE Col1 = 15 6 ROLLBACK
我會收到如下的錯誤信息:
因此,我們給查詢本身加上查詢提示:
1 BEGIN TRANSACTION2 3 UPDATE TestTable WITH (SNAPSHOT) SET Col2 = 'Test' WHERE Col1 = 14 5 SELECT * FROM sys.dm_tran_locks6 WHERE request_session_id = @@SPID7 8 COMMIT9 GO
現(xiàn)在事務(wù)已經(jīng)提交,sys.dm_tran_locks 再一次只顯示了Sch-S鎖。下一步我想做的是嘗試并行執(zhí)行2個UPDATE語句,但不提交第1個事務(wù)。因此我們在2個不同的會話執(zhí)行下列語句,并確保2個事務(wù)都不提交。
1 BEGIN TRANSACTION2 3 UPDATE TestTable WITH (SNAPSHOT) SET Col2 = 'Test' WHERE Col1 = 1
沒有XTP,第2個事務(wù)會阻塞,因為X鎖正被第1個事務(wù)拿著:
很遺憾SQL Server在第2個會話里給我們下列的錯誤信息:
我們的執(zhí)行進入更新沖突(Update Conflict),SQL Server回滾了第2個事務(wù)。我并沒有料到這點,但我需要對此仔細思考下。
在當前SQL Server 2014 CTP1版本里,XTP提供給你的另一個東西叫做 本機編譯的存儲過程(Natively Compiled Stored Procedures):
又一次,沒有向?qū)В挥心阋玫降腡-SQL腳本模板。本機編譯(Native Compilation)意味這SQL Server在后臺將整個存儲過程編譯至C/C++代碼——這個性能將會是卓越的,因為現(xiàn)在我們在SQL Server內(nèi)部直接執(zhí)行本機代碼(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.TestTable16 END17 GO
有幾個屬性必須要知道:
當你完成存儲過程創(chuàng)建后,你就可以執(zhí)行它了:
1 EXEC HekatonProcedure 52 GO
因為現(xiàn)在你用的是本機代碼,那就沒有執(zhí)行計劃了!好好享受這執(zhí)行速度……ALTER PROCEDURE也不支持了(沒意義,因為是本地生成代碼(native generated code)),意味如果你想修改這個存儲過程的話,你還不能再次DROP和CREATE。
這是我第一次安裝SQL Server 2014體驗XTP的簡短過程。更多的信息和內(nèi)容,我定會在接下來的文章里和大家一起分享。請繼續(xù)關(guān)注!
新聞熱點
疑難解答
圖片精選