MongoDB で トランザクション を利用する方法

0 件のコメント

今回は MongoDB 4.0 で追加された 「トランザクション」 の利用方法 についてまとめます。

概要

2018年6月27日にリリースされた MongoDB 4.0 には、新機能として「マルチドキュメントトランザクション」が追加されました。 基本の設計は非正規化したドキュメント構造ですが、どうしても分割されてしまうドキュメントが出ないとは言い切れません。 そんな時に「トランザクション」はデータの整合性を保つうえで重要な機能になります。

では、以下で実際にトランザクションを利用した Node.js からのDB操作のサンプル実装および動作確認をしていきます。

前提準備

利用するモジュールは以下のものになります。 サーバーサイドとクライアントサイドは対になっていますので、両方が利用したい機能を含んだバージョン以上でないと使えません。 トランザクション機能が使うためには、サーバーは MongoDB 4.0 以上、クライアントは MongoDB Node.js Driver 3.1 以上を利用します

さて、これでトランザクションが利用できるのかと思いきや…実は「トランザクション」が利用できるのは「レプリカセット構成」か「シャーディング構成」の時だけでした。 つまり「スタンドアローン構成」で「トランザクション」は利用できません。 なので、以下の記事を参考に「レプリカセット構成」を準備します。

※補足

ちなみに、スタンドアローン構成で実行すると以下のようなエラーが出ます。

"Transaction numbers are only allowed on a replica set member or mongos"

また、公式ドキュメントにも以下のような記述がります。 このことから、トランザクションはレプリカセットないしシャーディングのための機能であることが読み取れます。

Starting in version 4.0, MongoDB provides the ability to perform multi-document transactions against replica sets.

実装例

前述の前提(MongoDB 4.0、MongoDB Node.js Driver 3.1、レプリカセット構成)が準備できている状況で、以下のようなソースを実行するとトランザクションを利用したDB操作が可能になります。

index.js

var MongoClient = require("mongodb").MongoClient;
var url = "mongodb://127.0.0.1:27001,127.0.0.1:27002,127.0.0.1:27003/";
var options = {
  family: 4,
  useNewUrlParser: true,
  replicaSet: "rs0"
};

MongoClient.connect(url, options, (error, client) => {
  var session = client.startSession();
  var db = client.db("sample");

  session.startTransaction();

  db.collection("users")
    .insertOne({ name: "tanaka" }, { session })
    .then((results) => {
      return session.commitTransaction();
    }).catch((error) => {
      return session.abortTransaction();
    }).then(() => {
      client.close();
    });
});
L2, 5, 6

URLの指定方法が MongoDB Node.js Driver 3.1 から変更されています。 useNewUrlParser: true を使う場合、接続URLに ?replicaSet="rs0" のように記述しただけではレプリカセットに接続できないので注意です。 オプション replicaSet: "rs0" を加える必要があります。

L10

セッションの開始は client.startSession() です。

L16

トランザクションが利用できるのはドキュメント操作全般(aggregate, find, delete, insert, update など)です。 対象となる具体的な操作は MongoDB Manual - Transactions : Transactions and Operations に記述があります。

L18, 20

ドキュメント操作が成功したら session.commitTransaction() を、失敗したら session.abortTransaction() を呼びます。 また、このとき return をつけて非同期が完了してから次へ進むようにしてあげます。 こうしないとコミットする前に client.close() が呼ばれてセッションが破棄されてしまいます。

動作確認

実行は通常の Node.js アプリケーション実行と同じで以下のようなコマンドでできます。

node "./index.js"

データ登録されているかどうかは実際に MongoDB へ接続して確認します。 接続先はレプリカセットのプライマリへ接続します。

mongo 127.0.0.1:27001

接続できれば以下のコマンドでデータ登録できていることを確認します。

PRIMARY > use sample
PRIMARY > db.users.find()

正しいコードだと本当にトランザクションが有効なのかわからないですが、コーディング途中でエラーを含んでいたりすると登録されていないことから有効になっていることが確認できます。 いろいろと試してみると良いと思います。

今回は「MongoDBにおけるトランザクションの利用補法」についてまとめました。 ポイントは以下の通りです。

  • 使うモジュールは以下のバージョン以上のもの
    • MongoDB Enterprise 4.0 +
    • MongoDB Node.js Driver 3.1 +
  • レプリカセット構成またはシャーディング構成で利用可能

参考になったでしょうか? 本記事がお役に立っていると嬉しいです!!

最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!