Overview
このガイドでは、PyMongo ドライバーを使用してトランザクションを実行する方法を学習できます。 トランザクション を使用すると、トランザクションがコミットされるまでデータを変更しない一連の操作を実行できます。 トランザクション内のいずれかの操作でエラーが返された場合、ドライバーはトランザクションをキャンセルし、変更が反映される前にすべてのデータ変更を破棄します。
MongoDBでは、トランザクションは論理セッション内で実行されます。セッションは 、順番に実行されるよう関連付けられた読み取り操作または書き込み操作のグループです。セッションを使用すると、ACID準拠のトランザクションで操作を実行できます。これは、アトミック性、整合性、分離、耐久性の期待を満たすトランザクションです。MongoDBは、トランザクション操作で予期せぬエラーが発生した場合でも、その操作に関わるデータの一貫性が保たれることを保証します。
PyMongo を使用すると、 MongoClientインスタンスからClientSession型の新しいセッションを作成できます。 毎回新しいクライアントを作成するのではなく、 MongoClientを複数のセッションやトランザクションで再利用することを推奨します。
警告
ClientSession は、それを作成した MongoClient(または関連付けられたMongoDatabase または MongoCollection)でのみ使用します。ClientSession と、異なる MongoClient を使用すると、操作エラーが発生します。
因果整合性
MongoDB は、クライアントセッションで因果整合性を有効にします。因果整合性モデルは、セッション内の操作が因果順序で実行されることを保証します。クライアントは、因果関係、または操作間の依存関係と整合性のある結果を観察します。例、ある操作が別の操作の結果に論理的に依存する一連の操作を実行すると、後続のすべての読み取りは 依存関係を反映します。
注意
クライアントセッションでは、トランザクションを実行しない場合でも因果整合性が有効になります。
次の表では、因果整合性のあるセッションが提供する保証について説明しています。
保証 | 説明 |
|---|---|
書込み操作の結果を読み取る | 読み取り操作は、前の書込み操作の結果を反映します。 |
単調な読み取り | 読み取り操作では、前の 読み取り操作よりも前のデータ状態を反映した結果は返されません。 |
単調書込み | 書込み操作が他の書込み操作に優先する必要がある場合、ドライバーはこの書込み操作を最初に実行します。 例、 |
書込み操作の前に読み取り操作をする | 書込み操作が他の読み取り操作の後に続く必要がある場合、ドライバーは最初に読み取り操作を実行します。 例、 |
因果関係が整合しているセッションでは、 MongoDB は次の操作のみの因果整合性を保証します。
majorityの読み取り保証 (read concern)がある読み取り操作majority書込み保証 (write concern)を持つ書込み操作
Tip
このセクションで述べられた概念の詳細については、次のMongoDB Serverマニュアル エントリを参照してください。
サンプル データ
このガイドの例では、 Atlas サンプル データセットのsample_restaurants.restaurantsコレクションを使用します。 MongoDB Atlas クラスターを無料で作成して、サンプル データセットをロードする方法については、 「 PyMongo を使い始める 」チュートリアルを参照してください。
メソッド
start_session()メソッドを使用してセッションを開始した後、返されたClientSessionによって提供される次のメソッドを使用してセッション状態を管理できます。
方式 | 説明 |
|---|---|
| このセッションで、指定されたオプションで構成された新しいトランザクションを開始します。セッションで既にトランザクションが実行中の場合はエラーを返します。このメソッドの詳細については、サーバー マニュアルの「startTransaction() ページ」を参照してください。 |
| 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. |
| このセッションのアクティブなトランザクションをコミットします。セッションにアクティブなトランザクションがない場合、またはトランザクションが終了した場合はエラーを返します。このメソッドの詳細については、サーバー マニュアルの commitTransaction() ページを参照してください。 |
| このセッションでトランザクションを開始し、 |
| セッションをコンテキストマネージャーの範囲内のすべてのデータベース操作にバインドします。 |
| このセッションを終了します。 トランザクションが開始された場合、このメソッドはそれを中止します。 終了するアクティブなセッションがない場合は、エラーを返します。 |
ClientSessionには、セッション プロパティを取得し、可変セッション プロパティを変更するメソッドもあります。 これらのメソッドの詳細については、 API ドキュメント を参照してください。
重要
bind(end_session=False) を呼び出す場合は、セッションがリークされないように、セッションの使用が終了したときに明示的に end_session() を呼び出す必要があります。次のコードは、正しい使用パターンと誤った使用パターンを示しています。
# Incorrect: leaks the session because no reference exists to call # end_session() on once finished with it with client.start_session().bind(end_session=False): ... # Correct: end_session=True by default, so session ends automatically with client.start_session().bind(): ... # Correct: session variable allows explicit cleanup with client.start_session() as s, s.bind(end_session=False): ... s.end_session() # Correct: nested context managers with client.start_session() as s: with s.bind(): ...
例
次の例は、以下の手順でセッションを作成し、トランザクションを作成し、複数のドキュメント挿入操作をコミットする方法を示しています。
start_session()メソッドを使用してクライアントからセッションを作成します。bind()メソッドを呼び出して、ブロック内のすべての操作にそれをバインドします。トランザクションを開始するには、
with_transaction()メソッドを使用します。複数のドキュメントを挿入します。セッションはバインドされているため、各操作から
session引数を省略できます。with_transaction()メソッドは挿入操作を実行し、トランザクションをコミットします。いずれかの操作でエラーが発生した場合、with_transaction()はトランザクションをキャンセルします。この方法により、ブロックが終了するときにセッションが適切に閉じられることが保証されます。client.close()メソッドを使用してサーバーへの接続を閉じます。
対応するコードを表示するには、Synchronous タブまたは Asynchronousタブを選択します。
# 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 async 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()
# Establishes a connection to the MongoDB server client = AsyncMongoClient("<connection string>") # Defines the database and collection restaurants_db = client["sample_restaurants"] restaurants_collection = restaurants_db["restaurants"] # Function performs the transaction async 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 await restaurants_collection_with_session.insert_one( {"name": "PyMongo Pizza", "cuisine": "Pizza"}, session=session ) await 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). await session.with_transaction(insert_documents) print("Transaction succeeded") except (ConnectionFailure, OperationFailure) as e: print(f"Transaction failed: {e}") # Closes the client connection await client.close()
トランザクションをさらに制御する必要がある場合は、 start_transaction()メソッドを使用できます。 このメソッドを前のセクションで説明した メソッドとcommit_transaction() abort_transaction()メソッドと組み合わせて使用すると、トランザクションのライフサイクルを手動で管理できます。
注意
並列操作はサポートされていません
PyMongo は、単一のトランザクション内での並列操作の実行中をサポートしていません。
MongoDB Server v8.0 以降を使用している場合は、MongoClientインスタンスで bulk_write() メソッドを呼び出すことで、1 つのトランザクション内で複数の名前空間に対して書込み操作を実行できます。詳細については、一括書込み (write) 操作のガイドを参照してください。
詳細情報
このガイドで言及されている概念の詳細については、 MongoDB Serverマニュアルの次のページ を参照してください。
ACID compliance の詳細については、 「 データベース管理システムの ACID プロパティとは 」を参照してください。 MongoDB Webサイトの記事。
API ドキュメント
このガイドで説明した型やメソッドの詳細については、次の API ドキュメントを参照してください。