交易中的資料爭用情況

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

交易和資料爭用

如要讓交易成功,交易讀取作業擷取的檔案不得由交易外部的作業修改。如果其他作業嘗試變更其中一個文件,該作業就會與交易發生資料爭用。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

伺服器用戶端程式庫會使用悲觀並行控制項,因為這類程式庫會假設延遲時間較短,且與資料庫的連線穩定。

在伺服器用戶端程式庫中,交易會鎖定讀取的檔案。交易對文件進行鎖定後,其他交易、批次寫入作業和非交易寫入作業就無法變更該文件。交易會在提交時釋出文件鎖定。如果逾時或因任何原因失敗,也會釋放鎖定。

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

可序列化隔離

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

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

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

可序列化隔離定義最高隔離等級。可序列化隔離層級是指:

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

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

Firestore 保證交易的可序列化隔離。Firestore 中的交易會依提交時間序列化及隔離。

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

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

實際執行交易需要一段時間。交易的執行作業會在提交時間前開始,且多項作業的執行作業可能會重疊。Firestore 會維持可序列化隔離,並保證:

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

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

交易內的隔離

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

資料爭用問題

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