Firebase Summit のすべての発表内容に目を通し、Firebase を活用してアプリ開発を加速し、自信を持ってアプリを実行できる方法をご確認ください。 詳細

トランザクションの直列化可能性と分離

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

このページでは、トランザクション データの競合、シリアル化可能性、および分離について説明します。トランザクション コードのサンプルについては、代わりにトランザクションとバッチ書き込みを参照してください。

トランザクションとデータ競合

トランザクションが成功するためには、その読み取り操作によって取得されたドキュメントが、トランザクション外の操作によって変更されないようにする必要があります。別の操作でそれらのドキュメントの 1 つを変更しようとすると、その操作はトランザクションとのデータ競合の状態になります。

データ競合
2 つ以上の操作が同じ文書を制御するために競合する場合。たとえば、あるトランザクションでは、並行操作がそのドキュメントのフィールド値を更新しようとしている間、ドキュメントの一貫性を維持する必要がある場合があります。

Cloud Firestore は、操作の 1 つを遅らせるか失敗させることで、データの競合を解決します。 Cloud Firestore クライアント ライブラリは、データの競合が原因で失敗したトランザクションを自動的に再試行します。再試行を有限回数行うと、トランザクション操作は失敗し、次のエラー メッセージが返されます。

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

失敗または遅延する操作を決定するときの動作は、クライアント ライブラリのタイプによって異なります。

  • モバイル/ウェブ SDK は、オプティミスティック同時実行制御を使用します。

  • サーバー クライアント ライブラリは、悲観的同時実行制御を使用します。

モバイル/ウェブ SDK でのデータ競合

モバイル/Web SDK (Apple プラットフォーム、Android、Web、C++) は、楽観的同時実行制御を使用してデータ競合を解決します。

オプティミスティック同時実行制御
データの競合が発生する可能性が低い、またはデータベース ロックを保持するのは効率的ではないという前提に基づいています。オプティミスティック トランザクションは、データベース ロックを使用して、他の操作によるデータの変更をブロックしません。

モバイル/ウェブ SDK は、待ち時間が長く、ネットワーク接続が不安定な環境で動作する可能性があるため、オプティミスティック同時実行制御を使用します。待機時間の長い環境でドキュメントをロックすると、データ競合の失敗が多すぎます。

Mobile/Web SDK では、トランザクションは、トランザクション内で読み取ったすべてのドキュメントを追跡します。トランザクションは、トランザクションの実行中にこれらのドキュメントが変更されなかった場合にのみ、書き込み操作を完了します。ドキュメントが変更された場合、トランザクション ハンドラはトランザクションを再試行します。数回再試行してもトランザクションがクリーンな結果を取得できない場合、トランザクションはデータの競合が原因で失敗します。

サーバー クライアント ライブラリでのデータ競合

サーバー クライアント ライブラリ (C#、Go、Java、Node.js、PHP、Python、Ruby) は、悲観的同時実行制御を使用してデータ競合を解決します。

悲観的同時実行制御
データの競合が発生する可能性が高いという仮定に基づいています。ペシミスティック トランザクションでは、データベース ロックを使用して、他の操作によるデータの変更を防ぎます。

サーバー クライアント ライブラリは、データベースへの低待機時間と信頼性の高い接続を想定しているため、悲観的同時実行制御を使用します。

サーバー クライアント ライブラリでは、トランザクションは読み取るドキュメントをロックします。ドキュメントに対するトランザクションのロックは、他のトランザクション、バッチ書き込み、および非トランザクション書き込みによるそのドキュメントの変更をブロックします。トランザクションは、コミット時にドキュメント ロックを解放します。また、何らかの理由でタイムアウトまたは失敗した場合にもロックを解除します。

トランザクションがドキュメントをロックすると、他の書き込み操作は、トランザクションがそのロックを解放するまで待機する必要があります。トランザクションは時系列でロックを取得します。

シリアライズ可能な分離

トランザクション間のデータ競合は、データベースの分離レベルと密接に関連しています。データベースの分離レベルは、システムが同時操作間の競合をどの程度うまく処理するかを表します。競合は、次のデータベース要件から生じます。

  • トランザクションには、正確で一貫したデータが必要です。
  • リソースを効率的に使用するために、データベースは同時に操作を実行します。

分離レベルが低いシステムでは、トランザクション内の読み取り操作は、同時操作のコミットされていない変更から不正確なデータを読み取る可能性があります。

シリアライズ可能な分離は、最高の分離レベルを定義します。シリアライズ可能な分離とは、次のことを意味します。

  • データベースは一連のトランザクションを実行すると想定できます。
  • トランザクションは、並行操作でコミットされていない変更の影響を受けません。

この保証は、データベースが複数のトランザクションを並行して実行している間も保持する必要があります。データベースは、この保証を破る競合を解決するために同時実行制御を実装する必要があります。

Cloud Firestore は、トランザクションのシリアライズ可能な分離を保証します。 Cloud Firestore のトランザクションは、commit 時間によってシリアル化および分離されます。

コミット時間によるシリアライズ可能な分離

Cloud Firestore は、各トランザクションに単一の時点を表すコミット時間を割り当てます。 Cloud Firestore がトランザクションの変更をデータベースにコミットすると、トランザクション内のすべての読み取りと書き込みがコミット時間に正確に行われると想定できます。

トランザクションの実際の実行には、ある程度の時間が必要です。トランザクションの実行はコミット時間の前に開始され、複数の操作の実行が重複する場合があります。 Cloud Firestore はシリアライズ可能な分離を支持し、次のことを保証します。

  • Cloud Firestore はコミット時間順にトランザクションをコミットします。
  • Cloud Firestore は、後の commit 時間でトランザクションを同時操作から分離します。

同時操作間でデータ競合が発生した場合、 Cloud Firestore は楽観的および悲観的な同時実行制御を使用して競合を解決します。

トランザクション内の分離

トランザクション分離は、トランザクション内の書き込み操作にも適用されます。トランザクション内のクエリと読み取りでは、そのトランザクション内の以前の書き込みの結果は表示されません。トランザクション内でドキュメントを変更または削除した場合でも、そのトランザクションで読み取られたすべてのドキュメントは、トランザクションの書き込み操作の前に、コミット時にドキュメントのバージョンを返します。ドキュメントが存在しなかった場合、読み取り操作は何も返しません。