跨容器交易

跨容器交易是隱含或顯式的使用者交易,包含對原生編譯的儲存程序的呼叫,或對記憶體優化資料表的操作。

在 SQL Server 中,呼叫儲存程序不會啟動交易。 以自動提交模式執行原生編譯程序(非使用者交易情境)不被視為跨容器交易。

任何引用記憶體最佳化資料表的直譯查詢,都被視為跨容器交易的一部分,無論是從明確或隱含的交易執行,或是自動提交模式。

個別作業的隔離

每個 SQL Server 交易都有隔離層級。 預設的隔離層級為已讀取承諾。 要使用不同的隔離等級,可以用 (Transact-SQL) 設定隔離等級SET TRANSACTION ISOLATION LEVEL。

通常需要在記憶體優化資料表上執行與磁碟資料表不同隔離層的操作。 在交易中,可以為一組語句或單一讀取操作設定不同的隔離層級。

指定個別操作的隔離層級

若要為交易中的一組語句設定不同的隔離層級,可以使用 SET TRANSACTION ISOLATION LEVEL。 以下交易範例預設使用可序列化隔離層級。 t3、t2 和 t1 上的插入與選擇操作皆在可重複讀取隔離下執行。

set transaction isolation level serializable  
go  
  
begin transaction  
 ......  
  set transaction isolation level repeatable read  
  
  insert t3 select * from t1 join t2 on t1.id=t2.id  
  
  set transaction isolation level serializable  
 ......  
commit  

若要設定個別讀取操作的隔離等級,且與交易預設不同,您可以使用表格提示(例如序列化)。 每個選擇都對應一次讀取操作,而每次更新與每次刪除都對應一次讀取,因為該列必須先被讀取,才能更新或刪除。 插入操作沒有隔離層級,因為寫入在 SQL Server 中始終是隔離的。 以下範例中,交易的預設隔離層級為讀取提交,但資料表 t1 是透過可序列化存取,t2 則是快照隔離。

set transaction isolation level read committed  
go  
  
begin transaction  
 ......  
  
  insert t3 select * from t1 (serializable) join t2 (snapshot) on t1.id=t2.id  
  
  ......  
commit  

個別操作的隔離語意

可序列化的交易 T 會被完全隔離執行。 這就像每隔一筆交易要麼在 T 開始前就已提交,要麼是在 T 提交後才開始。 當交易中不同操作的隔離層級不同時,情況會變得更複雜。

SQL Server 中交易隔離層級的一般語意,以及對鎖定的影響,詳見 SET TRANSACTION ISOLATION LEVEL (Transact-SQL)。

對於跨容器交易,不同操作可能有不同的隔離層級,你需要了解個別讀取操作隔離的語意。 寫入操作總是被隔離的。 不同交易中的寫入不會互相影響。

資料讀取操作會回傳滿足過濾條件的若干列。

讀取作為交易 T 的一部分執行。讀取操作的隔離層級可理解為:

提交狀態
提交狀態指的是資料讀取是否保證會被提交。

(交易型)一致性
一組讀取的事務一致性是指所讀取的每一列版本是否都保證包含來自完全相同交易集合的更新。

穩定性保證系統會將資料讀取的資訊傳遞給交易 T。
穩定性指的是交易的讀取是否可重複進行。 也就是說,如果重複讀取,會不會回傳相同的行和行版本?

某些保證指的是交易的邏輯結束時間。 一般而言,邏輯結束時間是指交易被提交到資料庫的時間。 如果交易存取的是記憶體優化的表格,邏輯結束時間技術上即為驗證階段的開始。 (更多資訊請參閱「 Memory-Optimized 表交易」中的交易生命週期討論。

無論隔離層級如何,交易 (T) 都會有自己的更新:

讀取未提交資料的隔離級別
讀取的資料可能既不提交、不一致也不穩定。 不過,它會包含 T 先前執行的寫入操作。

讀取已提交
讀取資料會被提交。

SNAPSHOT
在快照隔離下,T 執行的所有讀取操作邏輯讀取時間相同,即交易開始時間。 資料讀取在邏輯讀取時間時保證已提交且一致。 從原始讀取時間重複讀取,保證會回傳相同的結果。

可重複讀取
資料讀取保證在交易邏輯結束時間前被提交且穩定。

可序列化
所有可重複讀取的保證,加上對 T 執行的所有可序列化讀取操作的幻影避免與交易一致性。幻影避免意味著掃描操作只能回傳由 T 寫入的額外列,而不能回傳其他交易所寫的列。

考慮以下交易,

set transaction isolation level read committed  
go  
  
begin transaction  
  -- remove all rows from t3; the related read operation is performed under read committed   
  -- isolation, as this is the default for the transaction  
  delete from t3  
  
  -- copy the contents from t1 to t3; the read on t1 is performed under the serializable   
  -- isolation level  
  insert t3 select * from t1 (serializable)  
  
  -- compare t3 and t1; note: the result set may not be empty, as rows may have been added   
  -- by other transaction before this select, due to the read committed isolation level  
  select * from t3 except t1  
  
  -- compare t1 and t3; note: the result set is empty, as no rows have been added to t1   
  -- since its contents were copied to t1, due to the serializable isolation level  
  select * from t1 except t3  
commit  

此交易刪除 t3 的所有列,採用可序列化隔離,複製所有從 t1 到 t3 的列,然後比較 t1 與 t3。 由於資料表清空,某些不在 t1 的列可能被加入了 t3。 由於副本可序列化,t1 未新增任何列。

雖然交易結束時從 t1 讀取的讀取在語法上已提交,但實際上是可序列化的,因為同一讀取在交易早期以可序列化隔離方式執行:序列化保證若在交易後續任何時刻讀取,仍返回相同的資料列。

跨貨櫃交易與隔離層級

跨容器交易可視為有兩側:磁碟端(用於磁碟資料表操作)與記憶體優化端(用於記憶體最佳化資料表操作)。 這兩邊的隔離程度可能不同。 事實上,兩側的個別讀取操作可能有不同的隔離等級。

若滿足以下任一條件,則該交易 T 的磁碟端達到某個隔離層 X:

  • 它從X開始。也就是說,會話預設是 X,要麼是因為你執行了 SET TRANSACTION ISOLATION LEVEL,要麼是 SQL Server 的預設值。

  • 交易過程中,預設隔離層級會被改為 X,使用 SET TRANSACTION ISOLATION LEVEL。

  • 在磁碟基礎資料表上執行讀取操作,在隔離層 X 下執行,語法 WITH (X)為 。

若在執行 T 時,對記憶體優化資料表的任何讀取操作或任何原生編譯的儲存程序都以隔離層 Y 執行,則 T 的記憶體優化端達到隔離層 Y。

以以下交易為例。 這裡,t1 和 t2 是基於磁碟的資料表,t3 和 t4 是記憶體優化資料表。

磁碟端的交易會達到已提交的隔離層級,因為它從該層級開始。 磁碟端也達到可重複讀取,因為第一次讀取操作是在該隔離層執行的。 交易結束時的刪除會在已讀取的已提交隔離層級執行,因此不會引入新的隔離層級。

記憶體優化端的交易可達到兩種層級之一:若條件1為真,則可序列化;若為假,則記憶體優化端僅能達到快照隔離。

set transaction isolation level read committed  
go  
  
begin transaction  
  select * from t1 (repeatableread)  
  
  if condition1 begin  
    insert t3 select * from t4 (serializable)  
  end  
  else begin  
    insert t3 select * from t4 (snapshot)  
  end  
  
  delete from t1  
commit  

支援跨容器交易的隔離層級

在跨容器交易中,對記憶體優化資料表的操作所使用的隔離層級有其限制。

記憶體優化資料表支援隔離層級快照、可重複讀取與可序列化。 對於自動提交交易,記憶體優化的資料表支援隔離層級 READ COMMITTED。

以下是支援的案例:

  • READ UNCOMMITTED、READ COMMITTED 及 READ_COMMITTED_SNAPSHOT 跨容器交易可在快照、可重複讀取及可序列化隔離下存取記憶體優化資料表。 READ COMMITTED 保證適用於該交易;交易讀取的所有列都已提交到資料庫。

  • 可重複讀取與可序列化的交易可在快照隔離下存取記憶體最佳化的資料表。

唯讀跨容器交易

大多數 SQL Server 只讀交易會在提交時被回滾。 由於資料庫中沒有變更可提交,系統會直接釋放交易所使用的資源。 對於只讀磁碟交易,交易中的所有鎖都會在此時釋放。 對於跨越單一原生編譯程序執行的只讀記憶體優化交易,則不進行驗證。

跨容器、唯讀的交易在自動提交模式下會在交易結束時直接回滾。 未執行任何驗證。

明確或隱含的跨容器唯讀交易,若交易在可重複讀取或可序列化隔離下存取記憶體優化資料表,則會在提交時執行驗證。 關於驗證的詳細資訊,請參閱 Memory-Optimized 表格交易中的衝突偵測、驗證與提交依賴檢查章節。

另請參閱

理解 Memory-Optimized 表上的交易
交易隔離層級與 Memory-Optimized 表的指引
Memory-Optimized 資料表交易重試邏輯的指引