データベース管理システムにおける ACID 特性ガイド
リアルタイムアプリケーションやモノのインターネット(IoT)デバイスの利用、そして非構造化データ資産の爆発的な増加に伴い、NoSQL データベースへの移行を進める組織がますます増えています。実際、NoSQL 市場は 2024 年から 2032 年にかけて年平均成長率(CAGR)24.9%で拡大し、2032 年には 745 億米ドル規模に達すると見込まれています。(IMARCグループ、2024 年)。
この成長は驚くべきことではありません。NoSQL データベース管理システム(DBMS)は、大規模かつ多様なデータセットを効率的に管理できるだけでなく、それらを対象としたビッグデータ分析にも適しているためです。
しかし、多くの人はいまだに、NoSQL DBMS では、多くの組織にとって重要な要件である ACID transaction の管理や ACID compliance を実現できないと考えています。実際には、その要件を十分に満たせる NoSQL DBMS も存在します。
この記事では、ACID transaction とは何か、ACID transaction の特性、ACID transaction が重要な理由、そして NoSQL DBMS における ACID transaction の例について説明します。
目次
- ACID transaction の簡単な歴史
- ACIDトランザクションとは何ですか?
- ACIDトランザクションはなぜ重要なのでしょうか?
- DBMS における ACID transaction の例
- MongoDBではACIDトランザクションはどのように機能しますか?
- MongoDB マルチドキュメントトランザクションはどのような場合に使用すべきですか?
- MongoDBでのトランザクションのベストプラクティスは何ですか?
- よくある質問
ACID transaction の簡単な歴史
ACID トランザクションの概念は、1970年代後半以降、現代のデータベースシステムの進化において中心的な役割を果たしてきました。
企業や研究機関がデジタルデータへの依存度を高めていくにつれ、複数のレコードにまたがる複雑な処理を確実に実行できる仕組みの必要性が明らかになりました。IBM の System R や Oracle などの初期のリレーショナルデータベースは、データの整合性とトランザクションの信頼性をより厳密に保証する仕組みの実現にいち早く取り組みました。
1983 年、コンピューター科学者の Andreas Reuter と Theo Härder は、画期的な論文の中で、4 つの ACID 特性である原子性、一貫性、独立性、永続性を正式に定義しました。この研究により、信頼性の高いデータベーストランザクションに求められる要件を共通の言葉で表現できるようになりました。各特性は、障害が発生した場合でもデータの正当性を維持し、処理を確実に実行するための異なる課題に対応しています。
- 原子性は、1 つのトランザクション内の複数の操作を不可分の単位として扱い、すべて成功するか、すべて失敗するかのいずれかであることを保証します。
- 一貫性は、データベースが定義済みのルールや制約を満たした正しい状態を常に維持できるようにします。
- 独立性は、同時に実行されるトランザクションが互いに干渉しないようにします。
- 永続性は、トランザクションがコミットされると、その結果はシステム障害が発生した後も永続的に保持されることを保証します。
このフレームワークは、リレーショナルデータベース管理システム(RDBMS)の事実上の標準となりました。特に銀行、小売り、通信といった、金融取引や規制遵守のために高い正確性が求められる業界で広く採用されるようになりました。
1990 年から 2000 年代初頭にかけて、Oracle、IBM DB2、Microsoft SQL Server などのリレーショナルデータベースが、先行書き込みログ、ロック、多版型同時実行制御などの手法を用いて、ACID 保証の実装を継続的に改善しました。
これらの手法により、組織は厳密な一貫性を維持しながら何百万件ものデータベース操作を処理できるようになりました。
2010 年代に NoSQL データベースが普及すると、水平方向のスケーラビリティと高可用性を重視して設計されたシステムでも、ACID 保証を維持できるのかという疑問が生まれました。初期の NoSQL プラットフォームでは、パフォーマンスと可用性を優先するために一貫性を緩和するものが多く、ACID compliance と NoSQL のスケーラビリティは両立できないという見方が広まりました。
しかし、分散システムにおいてもデータの整合性がますます重視されるようになると、MongoDBなどのベンダーは、マルチドキュメントトランザクションをサポートしながら、複数ノードへのスケールアウトも実現できることを示しました。
今日でも、ACID transaction の重要性は変わっていません。銀行口座間の送金から医療記録の管理まで、ミスが許されない分野において、データの整合性を維持するための基盤となっています。
同時に、MongoDB のような最新プラットフォームでは、柔軟な非構造化データや分散クラスター全体にまたがる複雑な操作にも ACID 保証を拡張しています。こうした信頼性とスケーラビリティの両立によって、40 年以上前に最初に確立された ACID の原則は、現在もデータベース管理の未来を支え続けています。
ACIDトランザクションとは何ですか?
トランザクションの解説
最も基本的には、データベーストランザクションとは、DBMSで定義された条件(トランザクションの成立条件など)を満たして正常に完了した、一連のデータベースの読み取り・書き込み操作を指します。トランザクションには、主に次の 2 種類があります。
- 単一トランザクション: 単一トランザクションとは、1 つ以上のデータベース操作からなる一連の操作で、最終的に 1 つのアクションが正常に完了することを指します。トランザクションが完了すると、そのトランザクションは確定され、トランザクションログで確認できます。代表的な例として、ATM での現金引き出しが挙げられます。
- マルチトランザクション: マルチトランザクションは、分散トランザクションとも呼ばれ、複数のデータベースやシステム(分散されたシステムなど)にまたがって実行される、相互に依存した複数のトランザクションで構成されます。これらのトランザクションもトランザクションログに記録されます。このようなトランザクションの例には、ある口座から別の口座への送金や、雇用主が新しい従業員に画像付きのセキュリティバッジを発行する処理などがあります。
重要なのは、一部のトランザクションでは、データの完全性(データが完全で正しい)とデータ一貫性(すべてのテーブルやデータベースで値が一致していること)について、厳格な基準を満たすことが求められる点です。これは、受託者責任や規制コンプライアンスが関係するシステムで特に重要になります。
例としては、商業銀行、証券会社、法的な決済・精算業務などがあります。
こうしたケースでは、DBMSの定義を標準的に満たしているだけでは不十分で、ACID transaction が必要です。
ACID transaction
ACIDは、Atomicity(原子性)、Consistency(一貫性)、Isolation(独立性)、Durability(永続性)の頭文字を取った略語です。これらの ACID 特性によって、1つのトランザクションとしてまとめられた一連のデータベース操作は、予期しないエラーが発生した場合でも、データベースを整合性の保たれた正しい状態に維持できます。
さらに、ACID transaction は、多くの規制当局が求めるレベルのトランザクション保証を提供します。
以下では、ACID transaction の各要素について概要を説明するとともに、NoSQL ドキュメントデータベースがそれぞれの要件をどのように実現しているのかを紹介します。本記事では、MongoDB Atlas を使用します。
アトミック性
原子性によって、トランザクションを構成するすべてのコマンドが 1 つの単位として扱われ、すべてが成功するか、すべてが失敗するかのいずれかになることが保証されます。これは、システム障害や停電などが発生した場合に特に重要です。トランザクションが最後まで正常に完了しなかった場合、そのトランザクションは破棄されるため、データベースのデータ整合性が維持されます。
MongoDB における原子性の扱い
MongoDB では、書き込み操作は、単一のドキュメント内の複数の埋め込みドキュメントを変更する場合でも、単一のドキュメントレベルで原子的に実行されます。
MongoDB は(単一のコレクションまたは複数のコレクション内の)複数のドキュメントへの読み取りと書込みに原子性を必要とする状況で、レプリカセットやシャーディングされたクラスターでのトランザクションを含む分散トランザクションをサポートしています。
整合性
一貫性とは、トランザクション内で行われた変更が、データベースシステム全体(各ノードなど)に反映され、DBMSの制約を常に満たすことを保証します。トランザクションの実行によってデータの一貫性が損なわれる場合、そのトランザクション全体は失敗します。
MongoDB における一貫性の扱い
MongoDBでは、アプリケーションの要件に応じて、データを正規化することも重複して保持することもできます。スキーマ内でデータを重複して保持する場合、複数のコレクションに存在する重複データの一貫性をどのように維持するかは、開発者が判断する必要があります。重複データを直ちに整合した状態に更新する必要があるアプリケーションもあれば、古いデータの読み取りを許容できるアプリケーションもあります。以下に例を示します。
注:データの一貫性について詳しく学ぶ。
分離
データの競合を防ぐために、各トランザクションは他のトランザクションから独立して実行されます。これにより、複数のデータ更新や、複数のトランザクションが同時に実行される環境でも、データベースは適切に処理を管理できます。
たとえば、2人のユーザーが同じデータ(または同じトランザクション)を変更しようとした場合、DBMSはロックマネージャーと呼ばれる仕組みを使用して、最初のユーザーによる変更が完了するまで他のユーザーの処理を待機させます。
MongoDB における独立性の扱い
MongoDBはスナップショット分離と呼ばれる技術を採用しています(たとえば、各トランザクションは、トランザクション開始時に取得されたデータベースのスナップショット上で動作しているように見えます)。トランザクションは、開始時点でコミット済みのデータのスナップショットからデータを読み取ることができ、競合する更新が発生した場合は、そのトランザクションは中止されます。
さらに、MongoDB のトランザクションでは、 トランザクションレベルの書込み保証(write concern) をサポートしています。クライアントは適切なレベルの読み取り保証(read concern)と書込み保証(write concern)を設定できます。最も厳格なレベルは、snapshot read concernとmajority write concernを組み合わせたものです。majority write concernでは、書き込み操作が、データを保持するノードの過半数(開発者が設定可能)に永続的にコミットされたことが保証されます。
耐久性
永続性は、トランザクションが完了し、その変更がデータベースに書き込まれると、その内容が永続的に保持されることを保証します。そのため、クラッシュや停止などのシステム障害が発生した場合でも、システム内のデータは保持されます。永続性の概念は、データの信頼性を支える重要な要素です。
MongoDB における永続性の扱い
MongoDB では、各書き込み操作について、OpLog にディスク上の書き込み先の位置と変更されたバイト列が記録されます。トランザクションの書き込み中に予期せぬイベント(停電など)が発生した場合でも、システムの再起動時に OpLog を使用して、シャットダウン前にディスクへ反映されなかった書き込みを再実行できます。
さらに、OpLog に記録される前に各操作が冪等となるよう変換されるため、同じ操作を複数回再実行できます。トランザクション(書き込み)は、デフォルトでは約 60 秒ごとにディスクへフラッシュされます。
ACIDトランザクションはなぜ重要なのでしょうか?
ACID transaction は、データの整合性と信頼性を維持するうえで重要な役割を果たします。また、政府や業界の規制の対象となる重要なデータ(銀行口座、株式ポートフォリオなど)が、求められる基準を確実に満たせるようにします。さらに、ACID compliance は、データレプリケーションを実装し、分散データベースシステムにおいて高可用性を実現するための前提条件となることも少なくありません。
DBMS における ACID transaction の例
NoSQL ドキュメントデータベースである MongoDB Atlas を用いて、ACID のマルチドキュメントトランザクションがどのように処理されるのか、また、ACID transaction が ACID の各特性で求められる基本要件をどのように満たしているかの例を紹介します。
ACIDマルチドキュメントトランザクション
たとえば、ある銀行口座から別の銀行口座へ送金する機能を実装するとします。それぞれの口座は個別のレコードです。送金元の口座からは正常に引き落としが行われたにもかかわらず、送金先の口座に入金されなかった場合、重大な会計上の問題が発生します。逆に、送金先の口座には入金されたものの、送金元の口座から引き落としが行われなかった場合も、同様に重大な会計上の問題が生じます。
これら2つの書き込み操作は、どちらも実行されるか、どちらも実行されないかのいずれかでなければならず、それによってシステムとデータの整合性が維持されます。さらに、トランザクション内のいずれかのコマンドが失敗した場合は、データベースはそのトランザクション中に適用したすべての変更をロールバック(取り消し)しなければなりません。
注:詳しく学ぶには、Node.js Quick Start GitHub リポジトリをご覧ください。サンプルコード一式を入手し、実際に実行して動作を確認できます。
注意すべき影響
分散システムでマルチドキュメントトランザクションを処理する際は、パフォーマンスのオーバヘッドが発生し、リソースの制約や目標とするパフォーマンスに影響を及ぼす可能性があることに注意してください。さらに、データベースは同時書き込みが互いに干渉(例:トランザクションの失敗)しないように、関係するリソースを「ロック」する必要があります。そのため、データを書き込もうとする他のクライアントは、トランザクションの完了を待たなければならず、アプリケーションのレイテンシやユーザー体験に影響を与える可能性があります。
MongoDBではACIDトランザクションはどのように機能しますか?
MongoDB のドキュメントモデルでは、関連するデータを 1 つのドキュメント内にまとめて保存できます。このドキュメントモデルと、ドキュメント単位での原子的な更新を組み合わせることで、多くのユースケースではトランザクションを使用する必要がありません。ただし、マルチドキュメント、マルチコレクションにまたがる本格的な MongoDB トランザクションが最適な選択肢となるケースもあります。
MongoDB のトランザクションは、他のデータベースのトランザクションと同様に機能します。トランザクションを使用するには、ドライバーを通じて MongoDB セッションを開始します。その後、そのセッションを使用して一連のデータベース操作を実行します。複数のドキュメント、コレクション、シャードにわたって任意の CRUD(作成、読み取り、更新、削除)操作を実行できます。
トランザクションの実装方法に関する具体的なコードサンプルについては、以下のクイックスタートをご覧ください。
- Golang を使用した MongoDB のマルチドキュメント ACID transaction
- Java を使用した MongoDB のマルチドキュメント ACID transaction
- Node.js を使用した MongoDB におけるマルチドキュメント ACID トランザクション
- Python を使用した MongoDB のマルチドキュメント ACID transaction
MongoDBが公式にサポートしている各言語に対応した言語別ガイドについては、MongoDBドライバーのドキュメントを参照してください。また、トランザクションに関するベストプラクティスや本番環境での留意事項の一覧もご覧いただけます。
MongoDB マルチドキュメントトランザクションはどのような場合に使用すべきですか?
トランザクションが必要となるアプリケーションは、一般的に、異なる当事者間で価値がやり取りされるユースケースを持っています。こうしたアプリケーションは、多くの場合、基幹業務システムや記録システムです。
マルチドキュメントトランザクションのメリットが得られるアプリケーションの例には、次のようなものがあります。
- 資金をある口座から別の口座へ移動させるシステム(銀行アプリケーション、決済処理システム、取引プラットフォームなど)。
- 製品やサービスの所有権をある当事者から別の当事者に移転するサプライチェーンシステムや予約システム
- 詳細なレコードと集計レコードの両方に情報を保存する請求システム。
MongoDBでのトランザクションのベストプラクティスは何ですか?
一般的には、一緒にアクセスされるデータは一緒に保存するようにデータモデルを設計することが推奨されます。このようにデータをモデリングすることで、パフォーマンスが向上するだけでなく、トランザクションも必要なくなります。
トランザクションを必要とするアプリケーションでは、以下のベストプラクティスに従ってください。
- 長時間実行されるトランザクションは小さな単位に分割して、デフォルトの 60 秒のタイムアウトを超えないようにします(このタイムアウトは延長可能です)。トランザクション内の操作でインデックスを使用し、高速に実行できるようにします。
- 1 回のトランザクションで変更するドキュメントは 1,000 件以内に制限します。
- 適切な読み込み保証(read concern)と書込み保証(write concern)を設定します(MongoDB バージョン5.0以降では、必要な majority write concern がデフォルトで使用されます)。
- 適切なエラー処理を実装し、一時的なエラーが原因で失敗したトランザクションはリトライできるようにします。
- 複数のシャードに影響を及ぼすトランザクションでは、パフォーマンスへの影響が大きくなることを考慮します。これらのベストプラクティスについて詳しくは、「MongoDB マルチドキュメント ACID トランザクション」ホワイトペーパーや、MongoDB のトランザクションに関するドキュメントを参照してください。
