トランザクション
Overview
このガイドでは、 MongoDB C++ドライバーを使用して トランザクション を実行する方法を学習できます。トランザクション を使用すると、トランザクションがコミットされるまでデータを変更しない一連の操作を実行できます。トランザクション内のいずれかの操作でエラーが返された場合、ドライバーはトランザクションをキャンセルし、変更が反映される前にすべてのデータ変更を破棄します。
MongoDBでは、トランザクションは論理 セッション 内で実行されます。セッションは 、順番に実行されるよう関連付けられた読み取り操作または書き込み操作のグループです。セッションにより、 ACID準拠のトランザクション内の操作のグループに対して因果整合性が有効になります。このトランザクションは、アトミック性、整合性、分離、耐久性に対する期待を満たすトランザクションです。 MongoDBは、トランザクション操作で予期せぬエラーが発生した場合でも、その操作に関わるデータの一貫性が保たれることを保証します。
C++ドライバーを使用すると、 mongocxx::client
インスタンスから新しいセッションを作成できます。その後、結果の mongocxx::client_session
インスタンスを使用してトランザクションを実行できます。毎回新しいクライアントをインスタンス化するのではなく、クライアントを複数のセッションやトランザクションで再利用することを推奨します。
警告
mongocxx::client_session
は、それを作成した mongocxx::client
でのみ使用します。 client_session
と別の client
を使用すると、操作エラーが発生します。
トランザクション API
MongoDB C++ドライバーは、トランザクション ライフを管理するためのコールバックAPIとコアAPIを提供します。トランザクションを開始する前に、start_session()
メソッドを呼び出して mongocxx::client_session
をインスタンス化する必要があります。その後、次のいずれかの API を使用してトランザクションを実行できます。
Callback API : トランザクションのライフサイクルを管理し、エラー処理ロジックを自動的に組み込む高レベルのAPI 。
Core API : トランザクションのライフサイクルを管理し、カスタムエラー処理ロジックを実装できる低レベルのAPI 。
Tip
エラー処理の詳細については、 MongoDB Serverマニュアルの「 トランザクション エラー処理 」セクションを参照してください。
Callback API
コールバック APIを使用して、 MongoDB C++ドライバーがトランザクションのライフサイクルを管理できるようにします。このAPIを実装するには、mongocxx::client_session
で with_transaction()
メソッドを呼び出し、実行する操作のシーケンスを指定するコールバック関数で渡します。 with_transaction()
メソッドはトランザクションを開始し、コールバック関数を実行し、エラーが発生した場合はトランザクションをコミットするか、トランザクションを終了します。トランザクションで TransientTransactionError
または UnknownTransactionCommitResult
エラーが発生した場合、with_transaction()
メソッドはトランザクションを再実行します。
次のコードでは、コールバックAPIを使用してトランザクションを実行し、sample_mflix
データベースの movies
コレクションと comments
コレクションにドキュメントを挿入します。このコードは、次のアクションを実行します。
start_session()
メソッドを使用してクライアントからセッションを開始します。トランザクション中に実行する操作を指定するコールバック関数を定義します。
トランザクション操作の書込み保証 ( 書込み保証 (write concern) ) を設定するために準備するオプションオブジェクトを作成します。読み取りと書込みセマンティクスの詳細については、 MongoDB Serverマニュアルの「読み取り保証/書込み保証/読み込み設定」セクションを参照してください。
コールバック関数とオプションオブジェクトを引数として渡して、トランザクションを管理するために
with_transaction()
メソッドを呼び出します。
// Establish a connection to the MongoDB deployment mongocxx::instance instance{}; mongocxx::client client(mongocxx::uri{"<connectionString>"}); // Define database and collection variables auto db = client["sample_mflix"]; auto movies_collection = db["movies"]; auto comments_collection = db["comments"]; // Define a callback specifying the sequence of operations to perform during the transaction mongocxx::client_session::with_transaction_cb callback = [&](mongocxx::client_session* session) { // Important:: You must pass the session to the operations. movies_collection.insert_one(*session, make_document(kvp("title", "Parasite"))); comments_collection.insert_one(*session, make_document(kvp("name", "Anjali Patel"), kvp("text", "This is my new favorite movie!"))); }; // Define an options instance to explicitly set the write concern for the transaction operations mongocxx::options::transaction opts; mongocxx::write_concern wc; wc.acknowledge_level(mongocxx::write_concern::level::k_majority); opts.write_concern(wc); // Start a client session auto session = client.start_session(); try { // Start a transaction, execute the operations in the callback function, and commit the results session.with_transaction(callback, opts); } catch (const mongocxx::exception& e) { std::cout << "An exception occurred: " << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS;
Core API
Core APIを使用して、トランザクションのライフサイクルを管理します。このAPIを実装するには、トランザクションを開始し、アクティブなトランザクションをコミットし、エラーが発生した場合はトランザクションを終了するために、mongocxx::client_session
インターフェースのメソッドを明示的に呼び出す必要があります。 Core APIにはエラー処理ロジックが自動的に組み込まれておらず、代わりに TransientTransactionError
や UnknownTransactionCommitResult
などのエラーに対するカスタム処理ロジックを実装できます。
次の表では、mongocxx::client_session
インターフェースが提供する主要APIメソッドについて説明しています。
方式 | 説明 |
---|---|
| Starts a new transaction on the current client session. Accepts an optional mongocxx::options::transaction
instance as an argument to set options. For a full list of options, see mongocxx::options::transaction
in the API documentation.Raises an exception if the options are misconfigured, if there are network or other transient failures, or if there
are other errors such as a session with a transaction already in progress. If an error is returned with the TransientTransactionError label,
you can end the transaction and then retry it with the expectation that it will succeed.To learn more about this method, see the startTransaction() guide in the MongoDB Server manual. |
| Commits the active transaction on the current client session. Raises an exception if options are misconfigured, if there are network or other transient failures,
or if there are other errors such as a session with no transaction in progress. If an error is returned with the UnknownTransactionCommitResult label,
you can end the transaction and then retry it with the expectation that it will succeed when the committed transaction satisfies the set write concern.To learn more about this method, see the commitTransaction() guide in the MongoDB Server manual. |
| Ends the active transaction on the current client session. Raises an exception if the options are misconfigured or if there are other errors such as
a session with no transaction in progress. To learn more about this method, see the abortTransaction() guide in the MongoDB Server manual. |
Tip
クラスには、セッションmongocxx::client_session
プロパティを検索および変更するメソッドも用意されています。詳細については、 APIドキュメントの「 mongocx::client_session 」を参照してください。
次のコードでは Core APIを使用してトランザクションを実行し、sample_mflix
データベースの movies
コレクションと comments
コレクションにドキュメントを挿入します。このコードは、次のアクションを実行します。
start_session()
メソッドを使用してクライアントからセッションを開始します。トランザクション操作の書込み保証 ( 書込み保証 (write concern) ) を設定するために準備するオプションオブジェクトを作成します。読み取りと書込みセマンティクスの詳細については、 MongoDB Serverマニュアルの「読み取り保証/書込み保証/読み込み設定」セクションを参照してください。
オプションオブジェクトを引数として渡してトランザクションを開始するための
start_transaction()
メソッドを呼び出します。アクティブなセッションを各操作に渡して、
sample_mflix
データベース内のコレクションにドキュメントを挿入する操作を実行します。ある操作でエラーが発生すると、トランザクション全体が中止されます。エラーにTransientTransactionError
のラベルがある場合、トランザクションは再試行されます。commit_transaction()
メソッドを使用してアクティブなトランザクションをコミットします。 コミットでラベルUnknownTransactionCommitResult
のエラーが発生した場合、コミットは再試行されます。
// Establish a connection to the MongoDB deployment mongocxx::instance instance{}; mongocxx::client client(mongocxx::uri{"<connectionString>"}); // Runs the txn_func and retries if TransientTransactionError occurs using transaction_func = std::function<void(mongocxx::client_session& session)>; auto run_with_retry = [](transaction_func txn_func, mongocxx::client_session& session) { while (true) { try { txn_func(session); // performs transaction. break; } catch (const mongocxx::operation_exception& oe) { std::cout << "Transaction aborted. Caught exception during transaction." << std::endl; // If transient error, retry the whole transaction. if (oe.has_error_label("TransientTransactionError")) { std::cout << "TransientTransactionError, retrying transaction..." << std::endl; continue; } else { throw oe; } } } }; // Commits the active transaction and retries commit if UnknownTransactionCommitResult occurs auto commit_with_retry = [](mongocxx::client_session& session) { while (true) { try { session.commit_transaction(); // Uses write concern set at transaction start. std::cout << "Transaction committed." << std::endl; break; } catch (const mongocxx::operation_exception& oe) { // Can retry commit if (oe.has_error_label("UnknownTransactionCommitResult")) { std::cout << "UnknownTransactionCommitResult, retrying commit..." << std::endl; continue; } else { std::cout << "Error during commit..." << std::endl; throw oe; } } } }; auto txn_func = [&](mongocxx::client_session& session) { auto& client = session.client(); // Define database and collection variables auto db = client["sample_mflix"]; auto movies_collection = db["movies"]; auto comments_collection = db["comments"]; // Define an options instance to explicitly set the write concern for the transaction operations mongocxx::options::transaction opts; mongocxx::write_concern wc; wc.acknowledge_level(mongocxx::write_concern::level::k_majority); opts.write_concern(wc); session.start_transaction(opts); // Attempt to insert documents into database collections try { movies_collection.insert_one(session, make_document(kvp("title", "Parasite"))); comments_collection.insert_one(session, make_document(kvp("name", "Anjali Patel"), kvp("text", "This is my new favorite movie!"))); } catch (const mongocxx::operation_exception& oe) { std::cout << "Caught exception during transaction, aborting." << std::endl; session.abort_transaction(); throw oe; } commit_with_retry(session); }; // Start a client session auto session = client.start_session(); try { run_with_retry(txn_func, session); } catch (const mongocxx::operation_exception& oe) { // Do something with error throw oe; }
詳細情報
このガイドで説明されている概念の詳細については、 MongoDB Serverマニュアルの次のページを参照してください 。
ACIDの詳細については、 MongoDBウェブサイトの「 データベース管理システムのACIDプロパティ 」ガイドを参照してください。
挿入操作の詳細については、ドキュメントの挿入ガイドを参照してください。
API ドキュメント
このガイドで説明した型やメソッドの詳細については、次の API ドキュメントを参照してください。