交易的可串行性和隔離性

本頁描述事務資料爭用、可串列性和隔離。有關事務程式碼範例,請參閱事務和批次寫入。

交易和數據爭用

為了使事務成功,透過其讀取操作檢索的文件必須保持不被事務外部的操作修改。如果另一個操作嘗試變更其中一個文檔,則該操作將進入與事務發生資料爭用的狀態。

數據爭用
當兩個或多個操作競爭控制同一個文件。例如,一個事務可能要求文件保持一致,而並發操作嘗試更新該文件的欄位值。

Cloud Firestore 透過延遲或失敗其中一項操作來解決資料爭用。 Cloud Firestore 用戶端程式庫會自動重試因資料爭用而失敗的交易。經過有限次數的重試後,事務操作失敗並傳回錯誤訊息:

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

在決定哪個操作失敗或延遲時,行為取決於客戶端庫的類型。

  • 行動/Web SDK 使用樂觀並發控制。

  • 伺服器客戶端庫使用悲觀並發控制。

行動/Web SDK 中的資料爭用

行動/Web SDK(Apple 平台、Android、Web、C++)使用樂觀並發控制來解決資料爭用。

樂觀並發控制
基於不可能發生資料爭用或持有資料庫鎖定效率不高的假設。樂觀事務不使用資料庫鎖來阻止其他操作更改資料。

行動/Web SDK 使用樂觀並發控制,因為它們可以在高延遲和不可靠網路連線的環境中運作。在高延遲環境中鎖定文件會導致過多的資料爭用失敗。

在行動/Web 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 使用樂觀和悲觀並發控制來解決爭用。

事務內的隔離

事務隔離也適用於事務內的寫入操作。事務內的查詢和讀取看不到該事務內先前寫入的結果。即使您在事務中修改或刪除文檔,該事務中的所有文檔讀取也會在提交時(在事務的寫入操作之前)返回文檔的版本。如果文件當時不存在,則讀取操作不會傳回任何內容。

數據爭用問題

有關數據爭用以及如何解決這些問題的更多信息,請查看故障排除頁面