この記事はFrancisco Munoz Alvarezによる“The Fundamentals of Reliability in the Context of Distributed Databases – Part 1”の日本語翻訳版です。
2023年12月1日
この連載記事では、同時実行制御、光のスピード、高可用性(HA)とディザスタ・リカバリ(DR)、コンセンサス・プロトコル/アルゴリズムなど、多くのエキサイティングなトピックをカバーします。
膨大で複雑なデータベース管理の世界では、トランザクションはデータの整合性と一貫性を確保する中心的な役割を果たします。複数のトランザクションを同時に実行することは、これらの重要な側面を維持する上で大きな課題となります。効率的で信頼性の高いデータ処理を求める要求が増え続ければ増え続けるほど、同時実行性制御メカニズムの複雑さを理解することが最重要になります。この記事では、データベースの世界におけるトランザクションと同時実行性の制御について説明し、共有リソースへのスムーズで同期されたアクセスを可能にする基本的な概念と手法について説明します。
トランザクションとその先
ではまず、基本的な概念であるトランザクションとは何かについてお話ししましょう。ご存知のように、トランザクションは、他の作業単位(トランザクション)から完全に独立した、1つの作業単位にグループ化されたDML (データ操作言語)操作の集合にすぎません。たとえば、ATM(Automated Teller Machine)を使用して、いくらかのお金を引き出すという仮想的なインスタンスを使用しましょう。カードをマシンに入力すると、トランザクションが開始され、PINが検証されます。次に、取引は100ドルの引出し要求で続行されます(このため、取引は現在の残高をチェックし、十分な金額がある場合は100ドルを減算して勘定科目データを更新します)。トランザクションがまだ実行中で、この時点まで未確認であることに注意してください。ATMがお金を与える前に、トランザクション全体を確認するように求められます。「はい」を選択した場合、トランザクションは承認(コミット)され、残高は信頼性の高い一貫した状態で保存されます。もちろん、お金を得ることができます。
一方、取消オプションを選択すると、このトランザクションに対するすべての操作が、発生しなかったかのように取り消されます(ロールバック)。最終的には、トランザクションは常にコミット(成功)またはロールバック(ユーザー、条件または失敗によって取り消される)で終了します。では、なぜトランザクションが重要なのでしょうか。トランザクションは、次のようないくつかの理由で不可欠です。
- トランザクションはデータの変更を表します。
- トランザクションは、インシデント(障害)の場合でもデータの一貫性を実現し、コミットされていないトランザクションをロールバックします。
- 一貫性を保つための完全な分離を提供し、すべてのデータの読取りと変更に一貫性を確保します。
MySQL、Oracle、PostgreSQLなどの従来のリレーショナル・データベースでは、ACIDと呼ばれるプロパティ・セットを使用して、考えられるエラー、電源障害などのインシデント、その他の不運に対するデータの妥当性を保証します。トランザクションの終了時に、トランザクション内のすべてのデータ編集がコミットされます。トランザクション内の1つの処理が失敗するか取り消された場合、トランザクション全体が繰り返され、変更は適用されません。すべてのステップが成功した場合、トランザクションは保持されます。このように、矛盾は決して問題になりません。これは、ACID内の原子性要件と完全に一致し、ACIDを満たす一連の操作をトランザクションと呼びます。
ACIDを理解する
ACIDは、Atomicity、Consistency、IsolationおよびDurabilityの頭字語であり、データベース内のデータの信頼性と整合性を確保する一連のプロパティです。これらの原則は、潜在的なエラーやインシデントに対するデータの妥当性を保証します。
第一に、原子性とは、データベース・トランザクションを分割できない作業単位として扱う必要があるという考え方を指します。これは、トランザクション内で行われたすべての変更が正常にコミットされるか、まったくコミットされないかのいずれかを要求します。この原則により、トランザクションの中間にエラーが発生した場合、すべての変更がロールバックされ、データの一貫性が維持されます。
第二に、一貫性により、トランザクション実行の前後にデータが有効であることを保証します。データベース内に格納されている値に対して特定のルールおよび制約を適用し、全体的な整合性を維持します。たとえば、操作がこれらの制約に違反した場合(重複した主キーの挿入など)、データベースの一貫性を保つためにトランザクション全体がロールバックされます。
第三に、分離によって、各トランザクションが同時に実行される他のトランザクションから独立することが保証されます。ロックやマルチバージョン並列性制御(MVCC)などの分離メカニズムにより、トランザクションは相互に干渉したり、操作中に一貫性のないデータ状態にアクセスしたりすることなく実行できます。
最後に、Durabilityは、トランザクションが正常にコミットされ、その変更が永続ストレージ・メディア(ディスクなど)に書き込まれると、後続のクラッシュや障害が存続することを保証します。このように、ACIDプロパティは、データの長期的な永続性を確保することで、潜在的なインシデントを保証します。
ロック戦略
データベースでは、複数のユーザーが同じリソースにアクセスする場合の一貫性を維持し、競合を回避することが不可欠です。そこで、明確なロック戦略が重要になります。表、データ行またはブロックのいずれであっても、これらのリソースは同時アクセスを許可しながら保護する必要があります。
適切に設計されたロック戦略により、更新の消失、ダーティ・リードおよび一貫性のない分析を防止できます。データベース・システムは、共有ロック(読取りロック)や排他ロック(書込みロック)などの適切なロック技術を実装することで、データの整合性を維持し、競合するトランザクションを適切に同期できます。ただし、ロック戦略が厳しく制限されると、ユーザー間で競合が発生しパフォーマンスが妨げられる可能性があり、一方でリラックスしすぎると一貫性が損なわれる可能性があります。
レコード・レベル・ロックや表レベル・ロックなど、使用可能な様々なタイプのロックを包括的に理解することで、可用性を最大限に高めながら同時実行レベルをきめ細かく制御できます。さらに、トランザクション分離レベルは、データベース・システム内でのロックの適用方法を決定する際に不可欠です。読取りコミットからシリアライズ可能な分離レベルまで- それぞれが、パフォーマンスと一貫性の保証とのトレードオフを提供します。
トランザクション分離レベルは、同時トランザクション間の分離度を制御する方法です。特定のトランザクションで表示またはアクセスできる他のトランザクションに関する情報量を決定します。データベースには、次のような複数の分離レベルを設定できます。
- Read-only: この分離レベルでは、トランザクションはデータベースの読取りはできますが、書込みはできません。これは、トランザクションがデータベース内のデータを表示できるが、変更できないことを意味します。
- Read-committed: この分離レベルでは、別のトランザクションがデータをコミットした場合にのみ、トランザクションがデータベースの読取りおよび書込みを実行できます。つまり、トランザクションはデータベース内のデータを参照できますが、他のトランザクションが作業を終了した後にのみ変更できます。
- Repeatable-read: この分離レベルでは、データが同じ場合にのみ、トランザクションでデータベースを複数回読み取ることができます。つまり、トランザクションはデータベース内のデータを参照できますが、データの読取り中は変更できません。
- Serializable: この分離レベルでは、トランザクションでデータベースを複数回読み取ることができますが、データが毎回同じ順序の場合のみです。つまり、トランザクションはデータベース内のデータを参照できますが、データの読取り中は変更できません。
要約すると、データベース・システムで複数のユーザー・アクセスを正常に処理するには、効果的なロック戦略を策定することが重要です。データの不整合から保護し、パフォーマンスを過度に犠牲にすることなく最大限の同時実行性を確保します。特定のロック・タイプとトランザクション分離レベルの選択は、アプリケーションの特定の要件に応じて異なります。保護とアクセシビリティの適切なバランスを取ることは、すべてのデータベース設計者が達成するために習得しなければならない技術です。
これは、同時実行制御が行われるときに重要です。たとえば、多数のユーザーがデータベースを同時に使用しているアプリケーションを作成する場合、複数のユーザーが同じデータまたはオブジェクトに同時にアクセスまたは更新しようとする場合があります。
データベースの同時実行性制御
さまざまな並行性制御スタイル(次の記事のトピック)の詳細に触れる前に、まずそれらが必要な理由を説明します。
同時実行制御(CC)は、すべてのデータベース・システムに不可欠であり、複数のユーザーがその整合性を損なうことなく、同時にデータにアクセスして変更できるようにします。データベースでは、同時実行性とは、様々なトランザクションが干渉することなく同時に実行される機能のことです。適切な同時実行性制御メカニズムがなければ、更新の損失、ダーティ読取り、一貫性のない結果など、いくつかの問題が発生する可能性があります。
データベース・システムで同時実行性制御が必要な主な理由の1つは、更新の消失を防ぐことです。この状況は、2つ以上のトランザクションが同じデータの更新を同時に試行する場合に発生します。適切な目安がないと、あるトランザクションの更新によって別のトランザクションの変更が上書きされ、データの不整合が発生する可能性があります。同時実行制御技術により、各トランザクションの変更が原子的かつ一貫して適用されるように、変更が適切にシリアライズされるようにします。
さらに、同時実行性制御の必要性を促進するもう1つの重要な要素は、データの分離を維持し、ダーティ・リードを防止することです。ダーティ・リードは、あるトランザクションがコミットされていないデータを別の同時実行で未完了のトランザクションから読み取る場合に発生します。「Read Commited」や「Serializable」などの適切なロック・レベルまたは分離レベルを実装することで、同時トランザクションは、データへの適切なロックが付与されたときにのみトランザクションを続行できるようにすることで、他のユーザーが行ったコミットされていない変更や不完全な変更にアクセスできなくなります。
データベース・システム内に効率的な同時実行性制御メカニズムを組み込むことで、コンカレント・プロセス間の競合を回避し、データの一貫性と整合性を維持しながら処理を確実に修正できます。これらの目標を達成することで、最終的にパフォーマンスと信頼性が向上すると同時に、分散システムやクラウド・コンピューティング・プラットフォームなどのネットワーク環境を介して共有データベースに同時にアクセスする際の、中断のないエクスペリエンスをユーザーに提供します。
まとめ
この記事では、データベース・システムの基礎的な概要について説明しました。トランザクション、ACIDプロパティ、分離レベルおよび同時実行性制御に重点を置いて、データベース・システムにおけるデータの整合性と一貫性を確保する重要なコンポーネントについて検討しました。トランザクションの動作方法とACIDプロパティの維持の重要性を理解することで、データベース内のデータの信頼性と精度を大幅に向上させることができます。
データベース管理システムの領域では、分離レベルおよび同時実行性制御は、トランザクション内のデータの整合性を確保するための基本的な要素です。分離レベルは、1つのトランザクションが他の同時トランザクションの影響から分離される度合いに関係します。一方、同時実行性制御とは、共有リソースへの同時アクセスを管理し、パラレル実行が原因で発生する可能性のある不整合を防止するメカニズムを指します。
分離レベルと同時実行性制御の違いは、それぞれの焦点にあります。分離レベルでは、主に個々のトランザクションの一貫性と整合性を維持することに重点を置き、同時実行性制御では、同時トランザクション間の相互作用の調整と管理に重点を置いています。基本的に分離レベルでは、トランザクションを他のユーザーの影響からどの程度保護できるかが指定されますが、同時実行性制御では、共有リソースに同時にアクセスする複数のトランザクションを編成します。
この分離レベルと同時実行性制御の複雑な関係を考えると、データベース・パフォーマンスの最適化において、これらが補完的かつ明確な目的を果たしていることが明らかになります。インタープレイを理解することで、リソースを効率的に利用できるだけでなく、データの信頼性を確保できます。これは、あらゆるデータベース・システム設計において重要な側面です。
What’s next
次の記事では、2つの重要な同時実行性制御方法(オプティミスティックとペシミスティック)とデータベース・システムへの影響について説明します。次回もお楽しみに。
