Docs Menu
Docs Home
/ /

チュートリアル: マルチドキュメントACIDトランザクションの実行

このチュートリアルでは、アトミック性、整合性、分離、 耐久性 (ACID)の保証を満たすマルチドキュメントトランザクションを実行する方法を学習できます。

すべてのMongoDB Serverバージョンは単一ドキュメントトランザクションをサポートし、トランザクション内でドキュメントに対して複数のアップデートを実行する場合はACIDコンプライアンスを保証します。 MongoDB Server v4.0 以降では、複数のドキュメント、コレクション、データベースにわたってACID準拠のトランザクションを実行できます。

このチュートリアルでは、製品の在庫と購入データのマルチドキュメントトランザクションを実行する 例アプリケーション をダウンロードする方法を説明します。チュートリアルでは、例アプリケーションのtransactions ディレクトリにある次のファイルを使用します。

  • Transactions.java: cartproduct コレクションにアクセスし、両方のコレクションに対して操作を実行して、ファイルの購入を反映します。このコードは、アプローチを比較するために、 ACIDトランザクション 内でトランザクションなしで動作します。

  • ChangeStreams.java: cart コレクションと product コレクションのデータ変更に関する情報を返します。

  • models/Cart.java: コレクション内のドキュメントに対応する、買い物かごを表す POJOクラス。cart

  • models/Product.java: productコレクション内のドキュメントに対応する、1 つのアイテムとその在庫を表す POJOクラス。

1

このチュートリアルを開始する前に、次のコンポーネントが準備されていることを確認してください。

2

MongoDB Developer GitHubリポジトリからサンプルアプリケーションを複製するには、ターミナルで次のコマンドを実行中。

git clone git@github.com:mongodb-developer/java-quick-start.git

このリポジトリには、このチュートリアルのファイルを保存する transactions フォルダーが含まれています。

3

コレクションと コレクションを作成し、 JSON スキーマを構成するには、cart productChangeStreams.javaファイルを実行します。 java-quick-startディレクトリに移動し、次のコマンドを実行します。

mvn compile exec:java \
-Dexec.mainClass="com.mongodb.quickstart.transactions.ChangeStreams" \
-Dmongodb.uri="<connection URI>"

Tip

<connection URI> プレースホルダーをクラスターの接続 URI に置き換えます。

このファイルは、次のアクションを実行します。

  • testデータベースに cartコレクションを作成します。

  • testデータベースに productコレクションを作成します。

  • ドキュメントフィールドにデータ型と値の制約を設定する productコレクションにJSONスキーマを適用します。このスキーマでは、stockフィールドの値が 0 以上に維持されます。これにより、在庫なしのアイテムを購入しようとするトランザクションはエラーがスローされ、成功しません。

  • 変更ストリームを開き、testデータベースへの変更をモニタリングします。

4

ミリ秒は、ファイルを購入したいサンプルカスタマーです。 Transactions.javaファイルは、の購入を反映するためにデータベース操作を実行します。このプログラムを起動するには、2 つ目のターミナルウィンドウを開き、プロジェクトのルートディレクトリから次のコードを実行します。

mvn compile exec:java \
-Dexec.mainClass="com.mongodb.quickstart.transactions.Transactions" \
-Dmongodb.uri="<connection URI>"

Tip

<connection URI> プレースホルダーをクラスターの接続 URI に置き換えます。

productファイルは、ファイルのコレクションに挿入し、そのstock 値を5 に設定します。このドキュメントには、次のデータが保存されています。

{ "_id" : "beer", "price" : NumberDecimal("3"), "stock" : NumberInt(5) }
5

サンプルデータを挿入した後、Transactions.javaファイルは最初の更新操作を実行して、アラートが 2 種類のファイルを購入したことを表します。このコードでは、トランザクションを開始せずに aliceWantsTwoBeers() メソッドと removingBeersFromStock() メソッドを呼び出します。これらのメソッドには、次の定義があります。

private static void aliceWantsTwoBeers() {
System.out.println("Alice adds 2 beers in her cart.");
cartCollection.insertOne(new Cart("Alice", List.of(new Cart.Item(BEER_ID, 2, BEER_PRICE))));
}
private static void removingBeersFromStock() {
System.out.println("Trying to update beer stock : -2 beers.");
try {
productCollection.updateOne(filterId, decrementTwoBeers);
} catch (MongoException e) {
System.out.println("######## MongoException ########");
System.out.println("##### STOCK CANNOT BE NEGATIVE #####");
throw e;
}
}

aliceWantsTwoBeers() メソッドは、購入を表す cartコレクションにドキュメントを挿入することで、Alice の買い物かごに 2 つのサーバーを追加します。次に、removingBeersFromStock() メソッドは productコレクションを更新して、変更を反映し、stock のベア数を減らします。

アラートの買い物かごを表す新しい cartドキュメントを表示するには、Cartタブを選択し、Productタブを選択して、操作後のファイルの在庫を表す productドキュメントを表示します。

{
"_id" : "Alice",
"items" : [
{
"price" : NumberDecimal("3"),
"productId" : "beer",
"quantity" : NumberInt(2)
}
]
}
{ "_id" : "beer", "price" : NumberDecimal("3"), "stock" : NumberInt(3) }
6

最初の購入後、アラートは 2 つのファイルを カードにさらに 2 つ追加します。 Transactions.javaファイルは操作を使用して、aliceWantsTwoExtraBeersInTransactionThenCommitOrRollback() メソッドを呼び出し、MongoClient を引数として渡します。このメソッドには、次の定義があります。

private static void aliceWantsTwoExtraBeersInTransactionThenCommitOrRollback(MongoClient client) {
ClientSession session = client.startSession();
try {
session.startTransaction(TransactionOptions.builder().writeConcern(WriteConcern.MAJORITY).build());
aliceWantsTwoExtraBeers(session);
sleep();
removingBeerFromStock(session);
session.commitTransaction();
} catch (MongoException e) {
session.abortTransaction();
System.out.println("####### ROLLBACK TRANSACTION #######");
} finally {
session.close();
System.out.println("####################################\n");
printDatabaseState();
}
}

aliceWantsTwoExtraBeersInTransactionThenCommitOrRollback() メソッドはセッションを開始し、トランザクションを開始します。トランザクション内で、コードはヘルパーメソッドを呼び出して次のアクションを実行します。

  • cartコレクション内で API のカーネルを表すドキュメントを見つける:

  • ドキュメントの items.quantity 値を 2 だけ更新

  • 変更を反映するように、スキーマを表す productコレクション内のドキュメントを更新します

マルチドキュメントACIDトランザクション内で実行されるため、cartproduct の更新はアトミックです。

Cartcartアラートの買い物かごを表す更新された ドキュメントを表示するには []タブを選択し、サーバー在庫を表す更新されたProduct productドキュメントを表示するには [2]タブを選択します。

{
"_id" : "Alice",
"items" : [
{
"price" : NumberDecimal("3"),
"productId" : "beer",
"quantity" : NumberInt(4)
}
]
}
{ "_id" : "beer", "price" : NumberDecimal("3"), "stock" : NumberInt(1) }
7

最後に、アラートはカードにさらに 2 つのファイルを追加しようとします。 Transactions.javaファイルはトランザクションを使用して、aliceWantsTwoExtraBeersInTransactionThenCommitOrRollback() メソッドを再度呼び出してこの 3 つ目の操作を実行します。

しかし、サーバーの在庫が 1 つしかないため、この操作は成功しません。 ChangeStreams.javaファイルで構成されているJSONスキーマにより、product コレクションの stock 値は 0 を下回ることはできないため、その現在の値から 2 を減算しようとするとエラーがスローされます。 aliceWantsTwoExtraBeersInTransactionThenCommitOrRollback() メソッドはトランザクションをロールバックします。

8

Transactions.java が の実行中を完了すると、ChangeStreams.java のファイル出力は次のようになります。

Dropping the 'test' database.
Creating the 'cart' collection.
Creating the 'product' collection with a JSON Schema.
Watching the collections in the DB test...
Timestamp{value=7304460075832180737, seconds=1700702141, inc=1} => Document{{_id=beer, price=3, stock=5}}
Timestamp{value=7304460075832180738, seconds=1700702141, inc=2} => Document{{_id=Alice, items=[Document{{price=3, productId=beer, quantity=2}}]}}
Timestamp{value=7304460080127148033, seconds=1700702142, inc=1} => Document{{_id=beer, price=3, stock=3}}
Timestamp{value=7304460088717082625, seconds=1700702144, inc=1} => Document{{_id=Alice, items=[Document{{price=3, productId=beer, quantity=4}}]}}
Timestamp{value=7304460088717082625, seconds=1700702144, inc=1} => Document{{_id=beer, price=3, stock=1}}

変更ストリームは、コレクションの構成と次の操作に関する情報を出力します。

  • 挿入操作。ドライバーを表す productコレクションにドキュメントを追加します。

  • アルゴリズムの最初の購入である 2 つのサーバーは、2 つの操作を含みます。1 つは cartコレクションを更新し、1 つは productコレクションを更新します。これらの操作はトランザクション内では実行されません。これらの操作は不可分的に実行されないため、異なる Timestamp 値があります。

  • アナライザの次回の 2 つのファイルの購入により、cartproductコレクションの両方も更新されます。これらの操作はマルチドキュメントトランザクションにおいてアトミックに実行されるため、同じ Timestamp 値を持ちます。

このチュートリアルを完了すると、株式管理データを更新するアプリケーションが作成されます。アプリケーションでは、マルチドキュメントACIDトランザクションの有無にかかわらずこれらのアップデート操作を実行し、2 つの結果を比較します。

完全な例アプリケーションを表示するには、java-quick-start GitHubリポジトリのトランザクション フォルダーを参照してください。

トランザクションの詳細については、トランザクションガイドを参照してください。

戻る

トランザクション