交易可序列化和隔離

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

交易與資料爭用

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

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

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 會使用樂觀和悲觀並行控制項來解決爭用問題。

交易內的隔離

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

資料爭用問題

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