共用方式為


Memory-Optimized 數據表中的交易

在基於磁碟的表中使用列版本控制(使用 SNAPSHOT 隔離或 READ_COMMITTED_SNAPSHOT)提供了一種樂觀併發控制的形式。 讀者和寫者不會互相封鎖。 使用記憶體優化數據表時,寫入器不會封鎖寫入器。 在磁碟基礎的資料表中使用行版本控制時,一個交易會鎖定該資料列,而嘗試更新該資料列的同時交易會被阻止。 記憶體優化資料表不會有鎖定。 相反地,如果兩筆交易嘗試更新相同的數據列,就會發生寫入/寫入衝突(錯誤 41302)。

不同於磁碟數據表,記憶體優化數據表允許使用較高隔離等級的樂觀並行控制,例如 REPEATABLE READ 和 SERIALIZABLE。 不會使用鎖定來實現隔離級別。 而是在交易驗證完成時,確保可重複讀取或可串行化假設。 如果違反假設,交易就會終止。 如需詳細資訊,請參閱 交易隔離等級

記憶體優化數據表的重要交易語意如下:

  • 多重版本控制

  • 快照式交易隔離

  • 樂觀的

  • 衝突偵測

下列各節將說明這些語意。

Memory-Optimized 數據表中的多重版本控制

記憶體優化數據表中的數據列可以有不同的版本。 並行交易存取可能不同版本的相同數據列。

記憶體優化資料表的資料是版本導向的。 對於任何數據列,可能會有不同的數據列版本在不同時間點有效。 當READ_COMMITTED_SNAPSHOT或ALLOW_SNAPSHOT_ISOLATION為 ON 時,磁碟數據表會維護不同的數據列版本。 即使將 READ_COMMITTED_SNAPSHOT 和 ALLOW_SNAPSHOT_ISOLATION 設為 OFF,記憶體優化資料表仍然會維護不同的列版本。 tempdb 中不會維護記憶體優化數據表的數據列版本。 相反地,數據列版本會內嵌維護,做為記憶體優化數據結構的一部分,以將數據列儲存在記憶體中。

Memory-Optimized 數據表的 Snapshot-Based 交易隔離

單一交易中的所有操作都會使用相同的記憶體最佳化資料表上的交易一致性快照。 記憶體優化數據表的所有交易隔離都是以快照集為基礎。 例如,使用可串行化隔離等級來存取記憶體優化資料表的交易,將會在相同的交易一致性快照上執行所有作業。

存取記憶體優化數據表的交易會使用此數據列版本設定來取得數據表中數據列的交易一致快照集。 交易中任何語句所讀取的數據,將會是交易啟動時所存在之數據的交易一致版本。 因此,目前交易中的語句看不到同時執行中交易所做的任何修改。

Memory-Optimized 表格的樂觀並行控制

衝突和失敗是罕見的,記憶體優化的資料表上的交易假設並行交易不會發生衝突,並且各項操作能夠成功。 交易不會對記憶體優化數據表採取鎖定或閂鎖,以確保交易隔離。 作者不會阻擋讀者。 作家不會阻礙作家。 相反地,交易會在(樂觀的)假設下進行,即不會與其他交易發生衝突。 不使用鎖定和閂鎖,且未等候其他交易完成處理相同的數據列可改善效能。

此外,如果交易(TxA)樂觀地假設其他交易(TxB)會認可,而不是等待認可發生,則會讀取由交易(TxB)在進行認可過程中插入或修改的數據列。 在此情況下,交易 TxA 將採用交易 TxB 的認可相依性。

衝突偵測、驗證和認可相依性檢查

SQL Server 會偵測同時進行交易之間的衝突以及隔離級別的違反,並終止其中一個衝突的交易。 必須重試此交易。 (如需詳細資訊,請參閱 Memory-Optimized 數據表上交易的重試邏輯指導方針

系統樂觀地假設沒有任何衝突,也不會違反交易隔離。 如果發生任何可能導致資料庫中不一致或可能違反交易隔離的衝突,則會偵測到這些衝突,並終止交易。

如果偵測到衝突,交易就會終止,而且用戶端需要重試。

下表摘要說明存取記憶體優化數據表之交易的錯誤狀況。

在存取記憶體優化資料表的交易中出現的錯誤狀況。

錯誤 情境
寫入衝突。 嘗試更新自交易啟動后已更新的記錄。 更新或刪除並行交易已更新或刪除的數據列。
可重複讀取驗證失敗。 交易讀取的數據列自交易啟動后已變更(已更新或刪除)。 使用 REPEATABLE READ 和 SERIALIZABLE 交易隔離等級時,通常會發生可重複讀取驗證。
序列化驗證失敗。 自交易啟動以來,已在交易的其中一個掃描範圍中插入新的 (虛設) 數據列。 如果該數據列在交易開始之前已提交到資料庫,該交易就能看到該數據列。 使用 SERIALIZABLE 隔離並驗證 PRIMARY KEY 約束條件時,通常會發生 SERIALIZABLE 驗證。
認可相依性失敗。 交易依賴於另一個未能提交的交易,這可能是由於表格中所列的某項失敗、記憶體不足的情況,或因無法提交至交易紀錄。 讀取/寫入和唯讀交易都可能發生此失敗。

交易存留期

在交易期間,上一個數據表中提及的失敗可能會發生在不同點。 下圖說明存取記憶體優化數據表之交易的階段。

交易的存留期。 存取記憶體優化數據表之交易的存留期。

一般處理

在這個階段中,會執行用戶發出的 Transact-SQL 語句。 數據列會從數據表讀取,而新的數據列版本會寫入資料庫。 交易會與所有其他並行交易隔離。 交易會使用交易開始時存在的記憶體優化資料表的快照。

在這個交易階段寫入表的操作其他交易仍無法看見,但有一個例外:資料列的更新和刪除對其他交易中的更新和刪除操作可見,以便偵測寫入衝突。

如果更新或刪除作業看到自交易邏輯啟動后已更新或刪除數據列,作業將會失敗,並出現錯誤 41302。 錯誤 41302 的訊息是「目前交易嘗試更新自此交易啟動後已更新的數據表 X 中的記錄。 交易已中止。

此錯誤會決定交易的命運(即使 XACT_ABORT 為 OFF),這表示當用戶會話結束時,交易將會回滾。 無法提交的交易只能支援讀取作業,這些作業不會寫入記錄檔且無法存取記憶體優化的資料表。

認可相依性

在一般處理期間,交易可以讀取其他交易在驗證或提交階段寫入的資料列,即使這些尚未提交。 數據列是可見的,因為交易的邏輯結束時間已在驗證階段開始時指派。

如果交易讀取這類未提交的資料列,則會對該交易產生提交依賴性。 這有兩個主要影響:

  • 在其依賴的交易已提交之前,交易無法提交。 換句話說,只有在所有相依性被解除後,它才能進入提交階段。

  • 此外,在清除所有相依性之前,結果集不會傳回給用戶端。 這可防止客戶端存取未提交的數據。

如果任何相依交易無法認可,就會發生認可相依性失敗。 這表示交易將無法認可,並出現錯誤 41301(「目前交易已中止的先前交易已中止,且目前交易無法再認可」)。

驗證階段

在驗證階段期間,系統會驗證要求之交易隔離等級所需的假設在交易的邏輯開始和邏輯結尾之間為 true。

在驗證階段開始時,交易會指派邏輯結束時間。 在邏輯結束時間,寫入資料庫中的數據列版本會變成其他交易可見。 如需詳細資訊,請參閱 認可相依性

可重複讀取驗證

如果交易的隔離等級是 REPEATABLE READ 或 SERIALIZABLE,或數據表是在 REPEATABLE READ 或 SERIALIZABLE 隔離下存取(如需詳細資訊,請參閱 交易隔離等級中個別作業隔離一節),系統會驗證讀取是否可重複。 這表示它會驗證交易讀取的數據列版本在交易的邏輯結束時間仍然是有效的數據列版本。

如果有任何數據列已更新或變更,交易將無法認可,錯誤為41305(「目前交易因可重複讀取驗證失敗而無法認可」。

如果在插入、更新或刪除作業之後,以及在交易認可之前卸載數據表,也可能會發生此錯誤。 這隻適用於原生編譯預存程式中的插入、更新或刪除作業。 透過解譯 Transact-SQL 執行的這類寫入操作會導致 DROP TABLE 語句被阻塞,並等待直到交易提交。

可串行化驗證

可串行化驗證會在兩種情況下執行:

  • 如果交易的隔離等級是SERIALIZABLE,或數據表是在SERIALIZABLE 隔離下存取。

  • 如果數據列插入唯一索引中,例如為 PRIMARY KEY 條件約束建立的索引。 系統會驗證沒有同時插入具有相同索引鍵的數據列。

系統會驗證尚未將虛設的數據列寫入資料庫。 系統會評估交易所執行的讀取作業,以判斷這些讀取作業的掃描範圍中不會插入任何新的數據列。

在唯一索引中插入索引鍵包含隱含讀取作業,以判斷索引鍵不是重複項。 唯一索引的可串行化驗證可確保在兩個交易同時插入相同鍵值時,這些索引不能有重複項目。

如果偵測到虛設數據列,交易將無法認可,錯誤為41325(「目前交易因可串行化驗證失敗而無法認可」。

提交處理

如果驗證成功且所有交易相依性都清楚,交易就會進入認可處理階段。 在此階段期間,永久性數據表的變更會寫入記錄檔,並將記錄寫入磁碟,以確保持久性。 將交易的記錄檔記錄寫入磁碟之後,控制權就會傳回給用戶端。

清除此交易的所有認可相依性,且所有等候此交易認可的交易都可以繼續。

局限性

  • 記憶體優化數據表不支援跨資料庫交易。 存取記憶體優化數據表的每個交易都無法存取多個資料庫,但tempdb的讀寫存取和系統資料庫 master 的唯讀存取除外。

  • 記憶體優化數據表不支持分散式交易。 以 BEGIN DISTRIBUTED TRANSACTION 開頭的分散式交易無法存取記憶體優化數據表。

  • 記憶體優化資料表不支援鎖定。 記憶體優化數據表不支援透過鎖定提示進行明確鎖定(例如 TABLOCK、XLOCK、ROWLOCK)。

另請參閱

瞭解 Memory-Optimized 數據表上的交易