Overview
このガイドでは、 MongoDB PHPライブラリを使用してトランザクションを実行する方法を学習できます。 トランザクションを使用すると、トランザクション全体がコミットされた場合にのみ、データを変更する一連の操作を実行できます。 トランザクション内のいずれかの操作が成功しない場合、ライブラリはトランザクションを停止し、変更が反映される前にすべてのデータ変更を破棄します。 この特徴はアトミック性と 呼ばれます。
MongoDB では、トランザクションは論理セッション内で実行されます。 セッションは 、順番に実行されるよう関連付けられた読み取り操作または書き込み操作のグループです。 セッションにより、一連の操作に対する 因果整合性 が有効になり、 ACID 準拠のトランザクション(アトミック性、整合性、分離、耐久性の期待を満たすトランザクション)内で操作を実行できるようになります。 MongoDBは、トランザクション操作で予期せぬエラーが発生した場合でも、その操作に関わるデータの一貫性が保たれることを保証します。
MongoDB PHPライブラリを使用すると、 MongoDB\Clientインスタンスから新しいセッションを作成できます。 その後、結果のMongoDB\Driver\Sessionインスタンスを使用してトランザクションを実行できます。
警告
Sessionは、それを作成したClientで実行されている操作でのみ使用します。 Sessionと別のClientを使用すると、操作エラーが発生します。
因果整合性
MongoDB は特定のクライアントセッションで因果整合性を有効にします。因果整合性モデルは、分散システム内でセッション内の操作が因果順序で実行されることを保証します。クライアントは、因果関係、または操作間の依存関係と整合性のある結果を観察します。例、ある操作が別の操作の結果に論理的に依存する一連の操作を実行すると、後続のすべての読み取りは 依存関係を反映します。
因果整合性を保証するには、クライアントセッションが次の要件を満たす必要があります。
セッションを開始するとき、ドライバーは 因果整合性 オプションを有効にする必要があります。このオプションはデフォルトで有効になっています。
操作は 1 つのスレッド上の 1 つのセッションで実行する必要があります。それ以外の場合、セッションまたはスレッドは optime とクラスター時間の値を相互に通信する必要があります。 これらの値を通信する 2 つのセッションの例については、 MongoDB Serverマニュアルの 因果整合性の例 を参照してください。
majorityの読み取り保証 (read concern)を使用する必要があります。majorityの書込み保証 (write concern)を使用する必要があります。これは、デフォルトの書込み保証 (write concern)の値です。
次の表では、因果整合性のあるセッションが提供する保証について説明しています。
保証 | 説明 |
|---|---|
書込み操作の結果を読み取る | 読み取り操作は、前の書込み操作の結果を反映します。 |
単調な読み取り | 読み取り操作では、前の 読み取り操作よりも前のデータ状態を反映した結果は返されません。 |
単調書込み | 書込み操作が他の書込み操作に優先する必要がある場合、サーバーはこの書込み操作を最初に実行します。 例、 |
書込み操作の前に読み取り操作をする | 書込み操作が他の読み取り操作の後に続く必要がある場合、サーバーは最初に読み取り操作を実行します。 例、 |
Tip
このセクションで述べられた概念の詳細については、次のMongoDB Serverマニュアル エントリを参照してください。
トランザクション API
このセクションでは、 MongoDB PHPライブラリが提供するトランザクション API について学習できます。 トランザクションを開始する前に、 ClientインスタンスでMongoDB\Client::startSession()メソッドを使用してSessionを作成する必要があります。 その後、次のいずれかの API を使用してトランザクションを実行できます。
Convenient API
MongoDB PHPライブラリは、トランザクションのライフサイクルを管理するためのConvenient Transaction APIを提供します。 このAPIを実装するには、 MongoDB\with_transaction()関数を使用してトランザクション内でカスタムコールバックを実行します。 with_transaction()関数は、次のタスクを実行します。
トランザクションを開始する
操作が を返した場合など、トランザクションを終了するか再試行することでエラーを処理します
TransientTransactionErrorトランザクションをコミットする
このガイドの「トランザクションの例」セクションでは、このAPIを使用してトランザクションを実行する方法を示します。
Core API
あるいは、 Sessionクラスが提供するメソッドを使用して、トランザクション ライフサイクルをより制御できます。 次の表では、これらの方法について説明します。
方式 | 説明 |
|---|---|
| このセッションで新しいトランザクションを開始します。セッションはトランザクション内の各操作に渡される必要があります。そうしないと、操作はトランザクションの外部で実行されます。オプション |
| このセッションのアクティブなトランザクションをコミットします。このメソッドは、セッションにアクティブなトランザクションがない場合、トランザクションが以前に終了された場合、または書込み競合 (write conflict)が発生している場合はエラーを返します。 |
| このセッションのアクティブなトランザクションを終了します。 このメソッドは、セッションにアクティブなトランザクションがない場合、またはトランザクションがコミットされたか、または終了した場合は、エラーを返します。 |
トランザクションの例
この例では、金融トランザクションのためにbankデータベースのコレクション内のデータを変更するコールバック関数を定義します。 このコードは、次のアクションを実行します。
ターゲット コレクションにアクセスするための
Collectionインスタンスを作成します。アカウント間で転送されるアカウント番号と金額を指定します。
コールバック関数を定義します。この関数は、
Sessionインスタンスをパラメータとして受け取ります。送金を反映するようにカスタマーの残高を更新します。
トランザクションの受信をタイムスタンプとともに記録します。
トランザクションが正常にコミットされた場合は、メッセージを出力します。
$receipts = $client->bank->receipts; $checking = $client->bank->checking_accounts; $saving = $client->bank->saving_accounts; $accountId = '5678'; $transferAmount = 1000.0; $callback = function (MongoDB\Driver\Session $session) use ( $checking, $saving, $receipts, $accountId, $transferAmount, ): void { $checking->updateOne( ['account_id' => $accountId], ['$inc' => ['balance' => -$transferAmount]], ['session' => $session], ); $saving->updateOne( ['account_id' => $accountId], ['$inc' => ['balance' => $transferAmount]], ['session' => $session], ); $summary = sprintf('SAVINGS +%1$u CHECKING -%1$u', $transferAmount); $receipts->insertOne( [ 'account_id' => $accountId, 'summary' => $summary, 'timestamp' => new MongoDB\BSON\UTCDateTime(), ], ['session' => $session], ); echo 'Successfully performed transaction!', PHP_EOL; echo 'Summary: ', $summary, PHP_EOL; };
次に、次のコードを実行してトランザクションを実行します。 このコードは、次のアクションを完了します。
startSession()メソッドを使用してクライアントからセッションを作成します。セッションとコールバックをパラメータとして渡して、トランザクションを管理するために
with_transaction()関数を呼び出します。
$session = $client->startSession(); try { MongoDB\with_transaction($session, $callback); } catch (MongoDB\Driver\Exception\RuntimeException $e) { echo 'Caught exception: ', $e->getMessage(), PHP_EOL; }
Successfully performed transaction! Summary: SAVINGS +1000 CHECKING -1000
注意
並列操作はサポートされていません
PHPライブラリは、単一のトランザクション内での並列操作の実行中をサポートしていません。
PHPライブラリ v2.1 以降とMongoDB Server v8.0 以降を使用している場合は、 メソッドを使用して、1MongoDB\Client::bulkWrite() つのトランザクション内で複数の名前空間に対して書込み操作を実行できます。詳細については、一括書込み (write) 操作 を参照してください。詳細情報
このガイドで言及されている概念の詳細については、 MongoDB Serverマニュアルの次のページ を参照してください。
ACID compliance の詳細については、 「 データベース管理システムの ACID プロパティとは 」を参照してください。 MongoDB Webサイトの記事。
挿入操作の詳細については、ドキュメントの挿入ガイドを参照してください。
API ドキュメント
このガイドで言及されているメソッドとタイプの詳細については、次のAPIドキュメントを参照してください。
Sessionクラスとメソッドの詳細については、次のPHP拡張APIドキュメントを参照してください。