交易可序列化和隔離

本頁說明交易資料爭用、可順序性和隔離性。如需交易程式碼範例,請改為參閱交易和批次寫入

交易和資料爭用

為了讓交易成功,透過讀取作業擷取的文件,必須保持未經過交易外部作業修改的狀態。如果其他作業嘗試變更其中一個文件,該作業就會進入與交易資料爭用的狀態。

資料爭用
當兩個以上的作業競相控制同一份文件時。舉例來說,某個交易可能需要文件保持一致,同時並行作業會嘗試更新該文件的欄位值。

Cloud Firestore 會延遲或失敗其中一個作業,藉此解決資料爭用問題。Cloud Firestore 用戶端程式庫會自動重試因資料競爭而失敗的交易。重試次數達到上限後,交易作業會失敗並傳回錯誤訊息:

ABORTED: Too much contention on these documents. Please try again.

決定要失敗或延遲哪項作業時,行為取決於用戶端程式庫的類型。

  • 行動/網頁 SDK 會使用樂觀並行控制項。

  • 伺服器用戶端程式庫會使用悲觀並行控制項。

行動/網頁 SDK 中的資料爭用

行動/網頁 SDK (Apple 平台、Android、Web、C++) 會使用最佳化並行控制項解決資料爭用問題。

最佳化並行控制
假設資料爭用情況不太可能發生,或是保留資料庫鎖定不具效率。樂觀式交易不會使用資料庫鎖定機制,阻止其他作業變更資料。

行動/網頁 SDK 會使用樂觀並行控制項,因為這些 SDK 可以在延遲時間長且網路連線不穩定的環境中運作。在高延遲環境中鎖定文件會導致過多資料爭用失敗。

在行動/網頁 SDK 中,交易會追蹤您在交易中讀取的所有文件。在交易執行期間,如果這些文件都沒有變更,只有在這種情況下,交易才會完成寫入作業。如果任何文件確實有變更,交易處理程式就會重試交易。如果交易在重試幾次後仍無法取得完整結果,則會因資料競爭而失敗。

伺服器用戶端程式庫中的資料爭用

伺服器用戶端程式庫 (C#、Go、Java、Node.js、PHP、Python、Ruby) 會使用悲觀並行控制項解決資料爭用問題。

悲觀並行控制
假設資料可能會發生爭用情形。悲觀式交易會使用資料庫鎖定機制,防止其他作業修改資料。

伺服器用戶端程式庫會使用悲觀並行控制項,因為這些控制項假設延遲時間短,且可靠地連線至資料庫。

在伺服器用戶端程式庫中,交易會在讀取的文件上鎖定。文件的交易鎖定會阻止其他交易、批次寫入作業和非交易寫入作業變更該文件。交易會在提交時釋放文件鎖定。並且在因任何原因逾時或失敗時釋放鎖定。

當交易鎖定文件時,其他寫入作業必須等待交易釋出鎖定。交易會依時間順序取得鎖定。

可序列化隔離

交易之間的資料爭用情況與資料庫隔離層級密切相關。資料庫的隔離層級說明系統處理並行作業之間的衝突情形的程度。衝突來自下列資料庫需求:

  • 交易需要準確且一致的資料。
  • 為了有效運用資源,資料庫會同時執行作業。

在隔離層級較低的系統中,交易中的讀取作業可能會從並行作業中未提交的變更讀取不正確的資料。

可序列化隔離定義最高隔離層級。可序列化隔離表示:

  • 您可以假設資料庫會依序執行交易。
  • 交易不會受到並行作業中未提交的變更影響。

即使資料庫同時執行多筆交易,也必須保證此保證。資料庫必須實作並行控制項,以便解決會破壞此保證的衝突。

Cloud Firestore 可確保交易的可序列化隔離。Cloud Firestore 中的交易會依據提交時間序列化和隔離。

依提交時間進行可序列化隔離

Cloud Firestore 會為每筆交易指派一個代表單一時間點的提交時間。當 Cloud Firestore 將交易的變更提交至資料庫時,您可以假設交易中的所有讀取和寫入作業會在提交時間準確執行。

交易實際執行的時間會有所差異。交易的執行作業會在提交時間之前開始,且執行多項作業可能會重疊。Cloud Firestore 會維持可序列化隔離,並保證:

  • Cloud Firestore 會依提交時間順序提交交易。
  • Cloud Firestore 會將交易與較晚的提交時間隔離,以便進行並行作業。

如果並行作業之間發生資料爭用情形,Cloud Firestore 會使用樂觀和悲觀並行控制項來解決爭用問題。

交易內的隔離

交易隔離功能也適用於交易中的寫入作業。交易內部的查詢和讀取作業不會看到先前在該交易中寫入的結果,即使您在交易中修改或刪除文件,該交易中的所有文件讀取作業都會在交易的寫入作業之前,傳回修訂時的文件版本。如果文件當時不存在,讀取作業就不會傳回任何內容。

資料爭用問題

如要進一步瞭解資料爭用問題及其解決方式,請參閱疑難排解頁面