Docs Menu

トランザクション

このガイドでは、PyMongo ドライバーを使用してトランザクションを実行する方法を学習できます。 トランザクション を使用すると、トランザクションがコミットされるまでデータを変更しない一連の操作を実行できます。 トランザクション内のいずれかの操作でエラーが返された場合、ドライバーはトランザクションをキャンセルし、変更が反映される前にすべてのデータ変更を破棄します。

MongoDBでは、トランザクションは論理セッション内で実行されます。セッションは 、順番に実行されるよう関連付けられた読み取り操作または書き込み操作のグループです。セッションを使用すると、ACID準拠のトランザクションで操作を実行できます。これは、アトミック性、整合性、分離、耐久性の期待を満たすトランザクションです。MongoDBは、トランザクション操作で予期せぬエラーが発生した場合でも、その操作に関わるデータの一貫性が保たれることを保証します。

PyMongo を使用すると、 MongoClientインスタンスからClientSession型の新しいセッションを作成できます。 毎回新しいクライアントを作成するのではなく、 MongoClientを複数のセッションやトランザクションで再利用することを推奨します。

警告

ClientSession は、それを作成した MongoClient(または関連付けられたMongoDatabase または MongoCollection)でのみ使用します。ClientSession と、異なる MongoClient を使用すると、操作エラーが発生します。

MongoDB は、クライアントセッションで因果整合性を有効にします。因果整合性モデルは、セッション内の操作が因果順序で実行されることを保証します。クライアントは、因果関係、または操作間の依存関係と整合性のある結果を観察します。例、ある操作が別の操作の結果に論理的に依存する一連の操作を実行すると、後続のすべての読み取りは 依存関係を反映します。

注意

クライアントセッションでは、トランザクションを実行しない場合でも因果整合性が有効になります。

次の表では、因果整合性のあるセッションが提供する保証について説明しています。

保証
説明

書込み操作の結果を読み取る

読み取り操作は、前の書込み操作の結果を反映します。

単調な読み取り

読み取り操作では、前の 読み取り操作よりも前のデータ状態を反映した結果は返されません。

単調書込み

書込み操作が他の書込み操作に優先する必要がある場合、ドライバーはこの書込み操作を最初に実行します。

例、insert_one() を呼び出してドキュメントを挿入し、update_one() を呼び出して挿入されたドキュメントを変更すると、ドライバーは最初に挿入操作を実行します。

書込み操作の前に読み取り操作をする

書込み操作が他の読み取り操作の後に続く必要がある場合、ドライバーは最初に読み取り操作を実行します。

例、find() を呼び出してドキュメントを取得し、delete_one() を呼び出して取得されたドキュメントを削除すると、ドライバーは最初に検索操作を実行します。

因果関係が整合しているセッションでは、 MongoDB は次の操作のみの因果整合性を保証します。

  • majority の読み取り保証 (read concern)がある読み取り操作

  • majority書込み保証 (write concern)を持つ書込み操作

Tip

このセクションで述べられた概念の詳細については、次のMongoDB Serverマニュアル エントリを参照してください。

このガイドの例では、 Atlas サンプル データセットsample_restaurants.restaurantsコレクションを使用します。 MongoDB Atlas クラスターを無料で作成して、サンプル データセットをロードする方法については、 「 PyMongo を使い始める 」チュートリアルを参照してください。

start_session()メソッドを使用してセッションを開始した後、返されたClientSessionによって提供される次のメソッドを使用してセッション状態を管理できます。

方式
説明

start_transaction()

Starts a new transaction, configured with the given options, on this session. Returns an error if there is already a transaction in progress for the session. To learn more about this method, see the startTransaction() page in the Server manual.

Parameters: read_concern, write_concern, read_preference, max_commit_time_ms
Return Type: ContextManager

abort_transaction()

Ends the active transaction for this session. Returns an error if there is no active transaction for the session or the transaction has been committed or ended. To learn more about this method, see the abortTransaction() page in the Server manual.

commit_transaction()

Commits the active transaction for this session. Returns an error if there is no active transaction for the session or if the transaction was ended. To learn more about this method, see the commitTransaction() page in the Server manual.

with_transaction()

Starts a transaction on this session and runs callback once, then commits the transaction. In the event of an exception, this method may retry the commit or the entire transaction, which may invoke the callback multiple times by a single call to with_transaction().

Parameters: callback, read_concern, write_concern, read_preference, max_commit_time_ms
Return Value: The result of the callback function

end_session()

Finishes this session. If a transaction has started, this method aborts it. Returns an error if there is no active session to end.

ClientSessionには、セッション プロパティを取得し、可変セッション プロパティを変更するメソッドもあります。 これらのメソッドの詳細については、 API ドキュメント を参照してください。

次の例は、以下の手順でセッションを作成し、トランザクションを作成し、複数のドキュメント挿入操作をコミットする方法を示しています。

  1. start_session()メソッドを使用してクライアントからセッションを作成します。

  2. トランザクションを開始するには、 with_transaction() メソッドを使用します。

  3. 複数のドキュメントを挿入します。 with_transaction()メソッドは挿入操作を実行し、トランザクションをコミットします。 いずれかの操作でエラーが発生した場合、 with_transaction()はトランザクションをキャンセルします。 この方法により、ブロックが終了するときにセッションが適切に閉じられることが保証されます。

  4. client.close()メソッドを使用してサーバーへの接続を閉じます。

# Establishes a connection to the MongoDB server
client = MongoClient("<connection string>")
# Defines the database and collection
restaurants_db = client["sample_restaurants"]
restaurants_collection = restaurants_db["restaurants"]
# Function performs the transaction
def insert_documents(session):
restaurants_collection_with_session = restaurants_collection.with_options(
write_concern=WriteConcern("majority"),
read_concern=ReadConcern("local")
)
# Inserts documents within the transaction
restaurants_collection_with_session.insert_one(
{"name": "PyMongo Pizza", "cuisine": "Pizza"}, session=session
)
restaurants_collection_with_session.insert_one(
{"name": "PyMongo Burger", "cuisine": "Burger"}, session=session
)
# Starts a client session
with client.start_session() as session:
try:
# Uses the with_transaction method to start a transaction, execute the callback, and commit (or abort on error).
session.with_transaction(insert_documents)
print("Transaction succeeded")
except (ConnectionFailure, OperationFailure) as e:
print(f"Transaction failed: {e}")
# Closes the client connection
client.close()

トランザクションをさらに制御する必要がある場合は、 start_transaction()メソッドを使用できます。 このメソッドを前のセクションで説明した メソッドとcommit_transaction() abort_transaction()メソッドと組み合わせて使用すると、トランザクションのライフサイクルを手動で管理できます。

注意

並列操作はサポートされていません

PyMongo は、単一のトランザクション内での並列操作の実行中をサポートしていません。

MongoDB Server v8.0 以降を使用している場合は、MongoClientインスタンスで bulk_write() メソッドを呼び出すことで、1 つのトランザクション内で複数の名前空間に対して書込み操作を実行できます。詳細については、一括書込み (write) 操作のガイドを参照してください。

このガイドで言及されている概念の詳細については、サーバー マニュアルの次のページを参照してください。

ACID compliance の詳細については、 「 データベース管理システムの ACID プロパティとは 」を参照してください。 MongoDB Webサイトの記事。

このガイドで説明した型やメソッドの詳細については、次の API ドキュメントを参照してください。