定義
Session.commitTransaction()マルチドキュメントトランザクションの操作によって行われた変更を保存し、トランザクションを終了します。
マルチドキュメントトランザクションは、シャーディングされたクラスターとレプリカセットの両方で使用できます。
Session.commitTransaction()は、値を返しません。重要
mongosh メソッド
This page documents a
mongoshmethod. This is not the documentation for database commands or language-specific drivers, such as Node.js.データベースコマンドについては、
commitTransactionコマンドを参照してください。MongoDB API ドライバーについては、各言語の「MongoDB ドライバーのドキュメント」を参照してください。
互換性
このメソッドは、次の環境でホストされている配置で使用できます。
- MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud
注意
This command is supported in all MongoDB Atlas clusters. For information on Atlas support for all commands, see Unsupported Commands.
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
動作
書込み保証 (write concern)
トランザクションをコミットする際、セッションはトランザクションの開始時に指定された書込み保証(write concern)を使用します。 詳しくはSession.startTransaction()を参照してください。
"w: 1" 書込み保証 (write concern) を使用してコミットすると、フェイルオーバー プロセス中にトランザクションがロールバックされる可能性があります。
アトミック性
トランザクションがコミットされると、トランザクションで行われたデータ変更はトランザクションの外部に保存、表示されます。つまり、トランザクションが他の変更をロールバックしながら、一部の変更をコミットすることはありません。
トランザクションがコミットされるまで、トランザクションで行われたデータ変更はトランザクションの外部には表示されません。
ただし、トランザクションが複数のシャードに書き込む場合、すべての外部読み取り操作が、コミットされたトランザクションの結果がシャード全体で表示されるまで待機する必要はありません。たとえば、トランザクションがコミットされ、書込み 1 がシャード A で表示されているものの、書込み 2 がシャード B にまだ表示されていない場合、読み取り保証(read concern) "local" での外部読み取りは、書き込み 2 を見ることなく書き込み 1 の結果を読み取ることができます。
再試行可能
コミット操作でエラーが発生した場合、MongoDB ドライバーは、 retryWritesがfalseに設定されているかどうかに関係なく、コミット操作を 1 回再試行します。 詳細については、「トランザクションエラーの処理 」を参照してください。
例
hr データベース内の従業員のレコードに変更が加えられたときに、reporting データベース内の events コレクションを hr の変更と同期させるシナリオを考えてみましょう。つまり、これらの書込み (write) が単一のトランザクションとして実行され、両方の操作が成功するか失敗するかのいずれかになるようにする必要があります。
hr データベースの employees コレクションには次のドキュメントが含まれています:
{ "_id" : ObjectId("5af0776263426f87dd69319a"), "employee" : 3, "name" : { "title" : "Mr.", "name" : "Iba Ochs" }, "status" : "Active", "department" : "ABC" } { "_id" : ObjectId("5af0776263426f87dd693198"), "employee" : 1, "name" : { "title" : "Miss", "name" : "Ann Thrope" }, "status" : "Active", "department" : "ABC" } { "_id" : ObjectId("5af0776263426f87dd693199"), "employee" : 2, "name" : { "title" : "Mrs.", "name" : "Eppie Delta" }, "status" : "Active", "department" : "XYZ" }
reporting データベースの events コレクションには次のドキュメントが含まれています:
{ "_id" : ObjectId("5af07daa051d92f02462644a"), "employee" : 1, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "ABC", "old" : null } } { "_id" : ObjectId("5af07daa051d92f02462644b"), "employee" : 2, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "XYZ", "old" : null } } { "_id" : ObjectId("5af07daa051d92f02462644c"), "employee" : 3, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "ABC", "old" : null } }
次の例では、トランザクションを開き、employees ステータスの従業員のステータスを Inactive に更新し、対応するドキュメントを events コレクションに挿入し、2 つの操作を 1 つのトランザクションとしてコミットします。
// Runs the txnFunc and retries if TransientTransactionError encountered function runTransactionWithRetry(txnFunc, session) { while (true) { try { txnFunc(session); // performs transaction break; } catch (error) { // If transient error, retry the whole transaction if (error?.errorLabels?.includes("TransientTransactionError") ) { print("TransientTransactionError, retrying transaction ..."); continue; } else { throw error; } } } } // Retries commit if UnknownTransactionCommitResult encountered function commitWithRetry(session) { while (true) { try { session.commitTransaction(); // Uses write concern set at transaction start. print("Transaction committed."); break; } catch (error) { // Can retry commit if (error?.errorLabels?.includes("UnknownTransactionCommitResult") ) { print("UnknownTransactionCommitResult, retrying commit operation ..."); continue; } else { print("Error during commit ..."); throw error; } } } } // Updates two collections in a transactions function updateEmployeeInfo(session) { employeesCollection = session.getDatabase("hr").employees; eventsCollection = session.getDatabase("reporting").events; session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } ); try{ employeesCollection.updateOne( { employee: 3 }, { $set: { status: "Inactive" } } ); eventsCollection.insertOne( { employee: 3, status: { new: "Inactive", old: "Active" } } ); } catch (error) { print("Caught exception during transaction, aborting."); session.abortTransaction(); throw error; } commitWithRetry(session); } // Start a session. session = db.getMongo().startSession( { readPreference: { mode: "primary" } } ); try{ runTransactionWithRetry(updateEmployeeInfo, session); } catch (error) { // Do something with error } finally { session.endSession(); }