Overview
このガイドでは、 MongoDB C++ドライバーを使用して トランザクション を実行する方法を学習できます。トランザクション を使用すると、トランザクションがコミットされるまでデータを変更しない一連の操作を実行できます。 トランザクション内のいずれかの操作でエラーが返された場合、ドライバーはトランザクションをキャンセルし、変更が反映される前にすべてのデータ変更を破棄します。
MongoDBでは、トランザクションは論理 セッション 内で実行されます。セッションは 、順番に実行されるよう関連付けられた読み取り操作または書き込み操作のグループです。 セッションにより、 ACID準拠のトランザクション内の操作のグループに対して因果整合性が有効になります。このトランザクションは、アトミック性、整合性、分離、耐久性に対する期待を満たすトランザクションです。MongoDBは、トランザクション操作で予期せぬエラーが発生した場合でも、その操作に関わるデータの一貫性が保たれることを保証します。
C++ドライバーを使用すると、 mongocxx::clientインスタンスから新しいセッションを作成できます。 その後、結果の mongocxx::client_sessionインスタンスを使用してトランザクションを実行できます。 毎回新しいクライアントをインスタンス化するのではなく、クライアントを複数のセッションやトランザクションで再利用することを推奨します。
警告
mongocxx::client_session は、それを作成した mongocxx::client でのみ使用します。 client_session と別の client を使用すると、操作エラーが発生します。
重要
mongocxx::client のインスタンスはスレッドセーフではありません。 各 mongoxcc::clientインスタンスとその子インスタンス(mongocxx::client_session を含む)は、一度に 1 つのスレッドで使用する必要があります。 詳しくは、「 スレッドとフォークの安全性ガイド 」を参照してください。
トランザクション API
MongoDB C++ドライバーは、トランザクション ライフを管理するための Callback APIと Core API を提供します。 トランザクションを開始する前に、start_session() メソッドを呼び出して mongocxx::client_session をインスタンス化する必要があります。 その後、次のいずれかの API を使用してトランザクションを実行できます。
Callback API : トランザクションのライフサイクルを管理し、エラー処理ロジックを自動的に組み込む高レベルのAPI 。
Core API : トランザクションのライフサイクルを管理し、カスタムエラー処理ロジックを実装できる低レベルのAPI 。
Tip
エラー処理の詳細については、 MongoDB Serverマニュアルの「 トランザクション エラー処理 」セクションを参照してください。
Callback API
Callback API を使用して、 MongoDB C++ドライバーがトランザクションのライフサイクルを管理できるようにします。 このAPI を実装するには、mongocxx::client_session で with_transaction() メソッドを呼び出し、実行する操作のシーケンスを指定するコールバック関数で渡します。 with_transaction() メソッドはトランザクションを開始し、コールバック関数を実行し、エラーが発生した場合はトランザクションをコミットするか、トランザクションを終了します。 トランザクションで TransientTransactionError または UnknownTransactionCommitResult エラーが発生した場合、with_transaction() メソッドはトランザクションを再実行します。
次のコードでは、コールバックAPI を使用してトランザクションを実行し、sample_mflixデータベースの movies コレクションと comments コレクションにドキュメントを挿入します。 このコードは、次のアクションを実行します。
start_session()メソッドを使用してクライアントからセッションを開始します。トランザクション中に実行する操作を指定するコールバック関数を定義します。
コールコールバック関数とオプションオブジェクトを引数として渡して、トランザクションを管理するために
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 インターフェースが提供する Core APIメソッドについて説明しています。
方式 | 説明 |
|---|---|
|
|
|
|
| 現在のクライアントセッションでアクティブなトランザクションを終了します。オプションが誤って設定されている場合、またはトランザクションが進行していないセッションなどのその他のエラーが発生した場合は、例外が発生します。このメソッドの詳細については、 |
Tip
mongocxx::client_sessionクラスには、セッション プロパティを検索および変更するメソッドも用意されています。詳細については、 APIドキュメントのmongocxx::client_sessionを参照してください。
次のコードでは Core API を使用してトランザクションを実行し、sample_mflixデータベースの movies コレクションと comments コレクションにドキュメントを挿入します。 このコードは、次のアクションを実行します。
start_session()メソッドを使用してクライアントからセッションを開始します。オプションオブジェクトを引数として渡してトランザクションを開始するための
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 ドキュメントを参照してください。