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