💭
[MongoDB]mongoshでBEGIN...COMMIT
概要
RDBで直接SQLを実行してデータを修正するようなケースにおいて、
BEGINを実行 -> データ修正クエリ -> データ確認クエリ -> 問題なければCOMMITを実行 
のようなトランザクションを利用したオペレーションを手動で行うこともあると思います。
MongoDBに対し、mongoshで同等の実行ができるかやってみました。
下記のドキュメントなど参考にしつつ、いくらか試してみてそれっぽくできたので備忘として記録します。
環境
MongoDB Atlas 4.4.15
やってみた
mongoshで、usersコレクションにinsertする処理をAbort/Commitしてみます。
実行はCompassのmongoshターミナルで実施しています。
セッション生成~データ登録
セッションオブジェクトの生成
> var session = db.getMongo().startSession()
トランザクション開始
> session.startTransaction({
    "readConcern": { "level": "snapshot" },
    "writeConcern": { "w": "majority" }
})
操作するコレクションを取得
> var users = session.getDatabase('test').getCollection('users')
インサート
> users.insertOne({name: "Yuto"})
// Result:
// { acknowledged: true,
//   insertedId: ObjectId("62ea2800b5612e419f621fda") }
インサートしたデータ確認
> users.findOne({name: "Yuto"})
// Result:
// { _id: ObjectId("62ea2800b5612e419f621fda"), name: 'Yuto' }
Abort
トランザクションをAbort
> session.abortTransaction()
インサートしたデータ確認(Abortされたのでヒットしない)
> users.findOne({name: "Yuto"})
// Result:
// null
Commit
トランザクションをコミット
> session.commitTransaction()
// Result:
// {
//   ok: 1,
//   '$clusterTime': {
//     clusterTime: Timestamp({ t: 1659513236, i: 109 }),
//     signature: {
//       hash: Binary(Buffer.from("df95ffba0897860cac7eb22e9604e6c14fbd53c5", "hex"), 0),
//       keyId: Long("7080911735359537154")
//     }
//   },
//   operationTime: Timestamp({ t: 1659513236, i: 109 })
// }
インサートしたデータ確認
> users.findOne({name: "Yuto"})
// Result:
// { _id: ObjectId("62ea2989b5612e419f621fdb"), name: 'Yuto' }
タイムアウト考慮
今回のような手動オペレーションでトランザクション内でコマンドを実行する場合、トランザクションのタイムアウト値(transactionLifetimeLimitSeconds, デフォルト60秒)によって途中でabortされてしまう可能性があります。
この値はAtlasの場合はユーザ側では変更できず、サポートに変更をリクエストする必要があるようです。
なお、現在のタイムアウト値は下記のコマンドで確認できます。
command
db.adminCommand({getParameter: 1, "transactionLifetimeLimitSeconds": 1})
result
{
  transactionLifetimeLimitSeconds: 60,
  ok: 1,
  ...
}
まとめ
BEGIN...COMMIT的なオペレーションが可能なことを確認できました。
需要のない記事とは思いますが、逆にすぐに情報出てこなかったので、どなたかの参考になれば幸いです。

Discussion