[SQL Server]dependent transaction with In-Memory table

SQL2014開始,Memory table的交易處理,有最大相依交易8的數量限制,只會發生在驗證和commit階段,

一般來說In-Memory的交易過程是非常短暫的,但這並不表示你的交易就不會失敗,

實務上,我一定會簡化Memory資料表相依(複雜)性,

雖然SQL2016 In-Memory table支援很多功能(FK、trigger、LOB..),但這不代表一定有效率。

當交易涉及到Memory table,交易的生命週期會有3個階段,如下

from Microsoft

一般處理

將Memory table中的row version視為邏輯處理開始時間。

Note:該階段有時也會產生update conflict,如果當下交易更新的row尚未commit,

但被其他交易先更新就會發生衝突。

41301:和現在交易相依的交易commit failure,那麼現在交易也會失敗。

 

驗證

邏輯處理(交易邏輯上算完成)結束後,緊接驗證階段,這時會將交易標記為邏輯處理已完成,

這時可以讓其他交易,看到這筆交易的所有變更,由於還未commit,

所以不會將交易後的結果傳回client,確保client只會接收到已經commit資料。

Repeatable Read:對於該isolation驗證,會檢查row是否有重複讀取,如有rows被其他交易更新,就會發生41305錯誤。

Serializable:對於該isolation驗證,會檢查row range是否有其他交易新增或刪除row,如有就會發生41325錯誤。

 

提交

提交階段,持久化資料表的變更會寫入log,log也會寫入disk,

都完成後才會把控制權交還給client,而其他所有的相依交易也都會收到commit完成通知。

 

Waiting

In-Memory世界交易還是有可能會發生等待,如果一個交易相依其他交易,

那麼該交易必須等其他交易commit並寫入disk後,自己才能commit,

這種commit相依的等待對於持久化資料表無法避免(schema_only就可以避開),

一般來說這過程相當短暫。

 

 

雖然In-Memory的交易效能很好,但我們應該還是要和以前一樣避免長時間交易,

因為Transaction還是有可能會發生等待情況(如有相依其他transaction)。

In-memory我們都知道沒有latch,blocking和deadlock,

但我還是有遇到並行交易衝突(retry就可解決)和相依交易限制的狀況,

如同我之前文章提到,索引和統計值在In-Memory世界依然重要,

尤其要避免big table scan(很多人總以為,In-Memory table可以大幅改善big table scan效能),

而這情況也是我們在disk table中,有可能發生的一種deadlock類型,下面我簡單重現。

 

我模擬big table scan,共1000次查詢

declare @eventcard [varchar](20)=''
select @eventcard=[event_card] from [dbo].[rsa241_mem] where emp_id='10.8.2.20 '

另一條session,我針對同樣的條件執行update(write transaction)

declare @i tinyint=1,@max tinyint=10
while(@i<=@max)
begin
BEGIN TRAN
	update [rsa241_mem] WITH (SNAPSHOT)  set [event_des] = REPLICATE(N'rico', 10) where emp_id='10.8.2.20 '
COMMIT
set @i=@i+1;
print 'transaction completed:'+cast(@i as varchar(5))
end

Note:write transaction completed,但交易會等待其他相依交易完成,所以交易效能會受影響。

結果

你可以看到1000次的big table scan,發生了214次的exceptions,

主因就是超過相依交易限制,下面我在使用extend event可以觀察更清楚。

-- Dependency Diagnostics Extended Events
-- Tracks error 41839 as well as TX dependency acquires
CREATE EVENT SESSION [TraceUserDependency] ON SERVER 
ADD EVENT sqlserver.error_reported(
    ACTION(sqlserver.session_id,sqlserver.sql_text)
    WHERE ([error_number]=(41839))),
ADD EVENT XtpEngine.dependency_acquiredtx_event(
    ACTION(sqlserver.session_id,sqlserver.sql_text,sqlserver.transaction_id,sqlserver.tsql_frame,sqlserver.tsql_stack)),
ADD EVENT XtpEngine.waiting_for_dependenciestx_event(
    ACTION(sqlserver.session_id,sqlserver.sql_text,sqlserver.transaction_id,sqlserver.tsql_frame,sqlserver.tsql_stack))
ADD TARGET package0.event_file(SET filename=N'D:\sqlevent\TraceUserErrors_Dependency.xel',max_file_size=(250),max_rollover_files=(2)),
ADD TARGET package0.histogram(SET filtering_event_name=N'sqlserver.error_reported',source=N'error_number',source_type=(0))
WITH (STARTUP_STATE=OFF)
GO

-- START
ALTER EVENT SESSION [TraceUserDependency] on SERVER STATE = START

我們可以清楚看到超過8個相依交易,當然,我這次簡單測試肯定有更多超過相依交易限制的錯誤。

 

MS告知可以開啟Trace flag 9926(DBCC TRACEON(9926,-1))來提高相依交易的限制數量,

但建議只有在未遺漏索引前提下才開啟,如果每筆交易都大量連入或連出,

且又存在複雜交易相依性,可能會造成系統沒效率。

 

參考

[SQL SERVER]Something about In-Memory isolation

Plan your adoption of In-Memory OLTP Features in SQL Server

Transactions with Memory-Optimized Tables

Transaction dependency limits with memory optimized tables – Error 41839

Use In-Memory OLTP to improve your application performance in SQL Database

Optimize performance by using In-Memory technologies in SQL Database