💭
[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