リアルタイムアプリケーションやモノのインターネット(IoT)デバイスの利用、さらに非構造化データ資産の急激な増加により、企業の NoSQL データベースへの移行は増加の一途をたどっています。2024年にIMARCグループが発表した調査レポートでは、NoSQL 市場は 2032 年までに 745 億米ドルに達し、2024 年から 2032 年までの成長率(CAGR)は 24.9% に達すると予測されています。
NoSQL データベース管理システム(DBMS)が、大規模で多様なデータセットやそれに関連するビッグデータ分析を効果的に管理できることを考慮すると、この成長は驚くべきことではありません。しかし、NoSQL DBMS は多くの組織にとって重要な要件である ACID トランザクション管理やコンプライアンスに対応できていないと考える人もまだ多く存在します。よいニュースとして、実際には一部の NoSQL DBMS は、この問題に対応していることがわかっています。
本記事では、ACID トランザクションとは何か、ACID トランザクションの特性、これらのトランザクションが重要な理由、また、NoSQL DBMS における ACID トランザクションのユースケースについて説明します。
目次
最も基本的なレベルでは、データベーストランザクションは、DBMS の定義(定義されたトランザクション基準など)に従って正常に完了したデータベースの読み取りおよび書き込み操作のグループです。トランザクションには主に 2 つのタイプがあります。
シングルトランザクション:シングルトランザクションとは、1 つのアクションが正常に完了する一連の 1 つ以上のデータベース操作のことです。完了すると、トランザクションは受理され、トランザクションログに記録されます。シングルトランザクションの一般的な例は、ATM からの現金の引き出しです。
マルチトランザクション:マルチトランザクション(分散トランザクションとも呼ばれる)は、異なるデータベースやシステムにまたがる複数の相互依存するトランザクションで構成されます。例えば、分散システムなどがあります。これらのトランザクションの記録はトランザクションログにもあります。このようなトランザクションの例としては、ある口座から別の口座への送金や、雇用主が新入社員に写真付きのセキュリティバッジを発行することなどがあります。
一部のトランザクションは、データの完全性(例:データが正確で完全であること)やデータの一貫性(例:値が全てのテーブルやデータベースで一致していること)の厳格な基準に従う必要があることを理解しておくことが重要です。このようなケースは、受託者責任や規制遵守が関係する場合によく見られます。例えば、商業銀行業務、投資仲介、法的決済などです。このような状況では、DBMS の定義に標準的に従うだけでは不十分で、ACID トランザクションが必要になります。このような状況では、DBMS の定義に標準的に従うだけでは不十分で、ACID トランザクションが必要になります。
ACID とは、atomicity(原子性)、consistency(一貫性)、isolation(独立性)、durability(永続性)の頭文字をとったものです。ACID プロパティは、予期しないエラーが発生した場合でも、一連のデータベース操作(トランザクションでグループ化)が有効な状態でデータベースを残すことを保証します。さらに、ACID トランザクションは、多くの規制機関が要求するレベルのトランザクション保証を提供します。
以下は、各 ACID トランザクション要素の概要と、NoSQ Lドキュメントデータベースがその ACID 要素を処理する方法についての説明です。本記事では、MongoDB Atlas を使用します。
原子性は、トランザクションを構成するすべてのコマンドが 1 つの単位として扱われ、成功または失敗が一貫して処理されることを保証します。これはシステム障害や停電が発生した場合に重要で、トランザクションが完全に処理されなかった場合は破棄され、データベースはデータの整合性を維持します。
MongoDB では、書き込み操作は単一のドキュメントレベルで原子性が保証されます。たとえその操作が複数の埋め込まれたドキュメントを変更する場合でも、単一のドキュメント内では原子性が保たれます。複数のドキュメントへの読み書きが同一のコレクションまたは複数のコレクション内で必要な場合は、MongoDB は分散トランザクションをサポートし、レプリカセットやシャードクラスタでのトランザクションも含まれます。
一貫性とは、トランザクション内で行われた変更がデータベースシステム(ノードなど)全体に反映され、DBMS の制約と一致していることを保証するものです。トランザクションが不整合な状態にある場合、その影響でデータの一貫性が損なわれると、トランザクション全体が失敗します。
MongoDB における一貫性の処理:MongoDB は、アプリケーションを最適化するためにデータの正規化や複製を行う柔軟性を提供します。スキーマ内でデータが重複している場合は、開発者は重複データを複数のコレクションで一貫性を保つ方法を決定する必要があります。アプリケーションによっては、重複したデータをすぐに一貫性を持たせる必要があります。一方で、他のアプリケーションでは古いデータを読み取ることが許容される場合もあります。以下に例を示します。
注: データの一貫性については、こちらをご覧ください。
各トランザクションは、データの競合を防ぐために、他のトランザクションから独立しています。これはまた、複数エントリや複数レベルのトランザクションの管理に関連するデータベース操作にも役立ちます。例えば、2 人のユーザーが同じデータ(あるいは同じトランザクション)を変更しようとしている場合は、DBMS はロックマネージャーと呼ばれるメカニズムを使って、最初のユーザーによる変更が完了するまで他のユーザーを一時停止させます。
MongoDBは「スナップショット独立性」と呼ばれる技術を採用しています(例えば、各トランザクションは、トランザクション開始時に撮影されたデータベースの個別のスナップショットで操作されるように見えます)。トランザクションは、トランザクション開始時にコミットされたデータの「スナップショット」からデータを読み込むことができ、競合する更新があった場合には、そのトランザクションは中断されます。
さらに、MongoDB のトランザクションはトランザクションレベルの読み込み と書き込みをサポートしています。クライアントは適切なレベルの読み込みと書き込みを設定できますが、最も厳密なのはスナップショット読み込みと多数派書き込みの組み合わせです。過半数の書き込みに関する懸念とは、書き込み操作がデータ保持ノードの計算上の過半数(開発者が設定可能)に持続的にコミットされていることを意味します。
永続性は、トランザクションが完了し、変更がデータベースに書き込まれると、それが永続化されることを保証します。これにより、クラッシュや停電のようなシステム障害が発生した場合でも、システム内のデータが持続することが保証されます。永続性の概念は、データの信頼性において重要な要素です。
MongoDB は、各「書き込み」で変更されたディスクの場所とバイト数を含む OpLog を作成します。トランザクションの書き込み中に不測の事態(停電など)が発生した場合は、システムが再起動したときに OpLog を使って、シャットダウン前にディスクにフラッシュされなかった書き込みを再生することができます。さらに、操作は OpLog に書き込まれる前に変更されるため、冪等であり、何度も再試行することができます。トランザクションや「書き込み」は、デフォルトではおよそ 60 秒ごとにディスクにフラッシュされます。
ACID トランザクションは、データの整合性と信頼性の維持に役立つと同時に、政府または業界の規制の対象となる重要なデータ(銀行口座、株式ポートフォリオなど)が要求される基準を満たすことを保証します。さらに、ACID準拠は、データのレプリケーションを実装し、分散データベースシステムで高可用性を実現するための前提条件であることがよくあります。
NoSQL ドキュメントデータベース MongoDB Atlas を使って、ACID マルチドキュメントトランザクションがどのように処理され、ACID トランザクションがどのように最小 ACID プロパティ標準へのアラインメントを保証するかの例を示します。
例えば、ある銀行口座から別の銀行口座に送金する機能を作成しているとします。送金元口座から送金されたお金が、送金先口座に入金されなかった場合は、深刻な会計上の問題が発生します。逆に、送金先口座には入金されたのに、送金元口座からは一度も引き落とされなかった場合には、別の深刻な会計上の問題が発生します。
この図は、ACID の特性が、ある銀行口座から別の銀行口座への送金の流れにどのような影響を与えるかを示しています。
この 2 つの書き込み操作は、システムとデータの一貫性を保つために、両方が実行されるか、両方とも実行されないかのどちらかでなければなりません。さらにこれは、トランザクションのいずれかのコマンドが失敗した場合には、データベースはトランザクションの過程で書き込まれた全ての変更をロールバック(元に戻すなど)が必要なことを意味します。
備考:詳しくは、 Node.js クイックスタート GitHub リポジトリをご確認ください。完全なコードサンプルのコピーを取得して実行できます。
分散システムでマルチドキュメントトランザクションを扱う場合は、パフォーマンスにオーバーヘッドが発生し、リソース制約やパフォーマンス目標に影響を与える可能性があることを覚えておくことが重要です。さらに、データベースはリソースを「ロック」して、トランザクションの失敗を防ぐためなど、並行して行われる書き込み操作が干渉しないようにする必要がある場合は、データを書き込もうとする他のクライアントがトランザクションの完了を待たされることがあります。このため、アプリケーションのレイテンシやユーザー体験に影響が出る可能性があります。
MongoDB のドキュメントモデルでは、関連するデータを 1 つのドキュメントにまとめて保存できます。このドキュメントモデルと原子性を持つドキュメント更新を組み合わせることで、大多数のユースケースではトランザクションを使用する必要がなくなります。しかし、本当の意味でのマルチドキュメント、マルチコレクションの MongoDB トランザクションが最適な選択となる場合もあります。
MongoDB のトランザクションは、他のデータベースのトランザクションと同じように動作します。トランザクションを使うには、ドライバーで MongoDB セッションを開始します。その後、そのセッションを使用してデータベース操作を実行します。複数のドキュメントやコレクション、シャードに対して CRUD(作成、読み込み、更新、削除)操作を実行できます。
トランザクションを実装する具体的なコードサンプルは、MongoDB Developer Center の クイックスタートを参照ください。
MongoDB が公式にサポートしている各言語のガイドについては MongoDB ドライバーのドキュメント を参照ください。また、トランザクションのベストプラクティスと運用上の注意の一覧は、こちらをご覧ください。
トランザクションを必要とするアプリケーションは通常、異なる当事者間で値を交換するユースケースを持ちます。これらは通常、「記録管理システム」または「基幹業務(LOB)」アプリケーションです。
マルチドキュメントトランザクションの恩恵を受ける可能性のあるアプリケーションの例には、次のようなものがあります。
ある口座から別の口座に資金を移動するシステム(銀行アプリケーション、支払処理システム、取引プラットフォームなど)。
商品やサービスの所有権がある当事者から別の当事者に移転されるサプライチェーンや予約システム。
詳細記録と概要記録で情報を保存する請求システム。
一般的に、同時にアクセスされるデータは、同じところに格納するようにデータをモデリングすることが推奨されます。このようにデータをモデル化すると、パフォーマンスが向上するだけでなく、トランザクションが不要になります。
トランザクションを必要とするアプリケーションでは、以下のベストプラクティスを遵守してください。
デフォルトの 60 秒のタイムアウトを超えないように、長時間実行するトランザクションを分割します。(このタイムアウトは延長可能です) トランザクション内の操作がインデックスを使用していることを確認し、迅速に実行されるようにしてください。
各トランザクションのドキュメントの修正は1,000件以内に制限します。
適切な 読み取りおよび書き込み の設定を行うようにします。(MongoDB 5.0 以降では、 デフォルトで「多数派書き込み」)に設定されています。)
適切なエラー処理を実装し、一時的なエラーによって失敗したトランザクションを再試行します。
複数のシャードに影響を与えるトランザクションはパフォーマンスにコストがかかる点を忘れないようにしてください。 これらのベストプラクティスについて詳しくは、MongoDB ホワイトペーパー「MongoDB のマルチドキュメント ACID トランザクション」や、トランザクションについての MongoDB ドキュメントを参照ください。
詳しくは、MongoDB Atlas をお試しください。MongoDB Atlas は、MongoDB のサービスとして完全に管理されたデータベースで、MongoDB を使い始める最も簡単な方法です。MongoDB Atlas クラスタを無料で作成して、トランザクションの利用を開始できます。