混沌から秩序へ: データベース内での同時実行性の制御の重要性 (2024/01/29)

混沌から秩序へ: データベース内での同時実行性の制御の重要性 (2024/01/29)

https://blogs.oracle.com/maa/post/from-chaos-to-order-the-importance-of-concurrency-control-within-the-database-2-of-6

投稿者: Francisco Munoz Alvarez | Distinguished Product Manager


<前の記事へのリンク>


データベースが同時環境でデータの一貫性を確保する方法について疑問に思ったことはありますか?オプティミスティックで悲観的な同時実行性制御は、この課題に正面から取り組む2つの基本的なアプローチです。オプティミスティックな同時実行性制御では、トランザクション間の競合はまれであると想定され、変更のコミットを試みるまで同時に続行できます。一方、悲観的な同時実行性制御は、操作を実行する前にリソースのロックを取得することによって慎重なアプローチをとります。この記事では、これらの2つの同時実行性制御モデルの複雑さを掘り下げ、異なる実装戦略を検討しながらその長所と短所を探ります。


オプティミスティック並行性制御(OCC)


オプティミスティック同時実行性制御(OCC、オプティミスティック・ロックとも呼ばれる)は、データベースの世界で同時トランザクションを処理するために一般的に使用されます。OCCは、操作を実行する前にデータ・リソースをロックする悲観的な同時実行性制御とは異なり、競合が発生する可能性が低いと仮定して、複数のトランザクションを同時に続行できるようにすることで、より簡潔なアプローチをとります。その後、レコードは、変更がデータベースにコミットされた場合にのみロックされます。この手法は、競合する更新をあとで検出して解決できるという考え方に依存します。


OCCの主な利点の1つは、悲観的アプローチと比較して高いスケーラビリティとパフォーマンスを実現できることです。ロックを取得せずに複数のトランザクションを同時に動作させることができるため、共有リソースに対する競合が最小限に抑えられ、デッドロック状況が発生する可能性が低くなります。さらに、このアプローチにより、ロック・メカニズムによる不要な遅延が回避され、全体的なシステム・スループットが向上します。


しかし、本質的に楽観的であることも、その欠点を伴います。OCCによって、同時トランザクション間で競合が頻繁に発生すると、多くの中断および再試行が発生する可能性があります。これは、アプリケーションのパフォーマンスに影響し、競合解決に必要な追加の処理のためにオーバーヘッドが発生する可能性があります。さらに、検出後の競合管理のみに依存しているため、トランザクションの実行中に一貫性のないデータが一時的に存在する可能性があります。


楽観的な同時実行性の利点


  • 高いレベルのスケーラビリティとパフォーマンス
  • アプリケーションのスケーリングに最適
  • 複数のユーザーのアクセス


楽観的同時実行性の連結


  • デッドロック回避を保証するものではありません。
  • これは、かなりの数の中断と再試行につながる可能性があります(収益の損失につながる可能性があります)。
  • トランザクションの実行中に、一貫性のないデータが一時的に存在する可能性があります。
  • 同時実行処理システムの手動実装が必要です(つまり、アプリケーションは、それらを処理するデータベースではなく、すべての同時実行性の競合を処理するように変更する必要があります。これについては後述します)。


オプティミスティックな同時実行性の実装


実際には、OCCはオプティミスティック・ロックと呼ばれるメカニズムに依存しています。共有データにアクセスする各トランザクションは、読み取るデータのバージョン番号またはタイムスタンプを保持します。トランザクションはその変更をライトバックする場合、データ・オブジェクトのバージョンが読取り後に変更されているかどうかをチェックします。更新が発生していない場合、変更は正常にコミットされます。それ以外の場合、トランザクションはロールバックされ、競合するデータの新しいコピーで再実行されます。


オプティミスティック同時実行性を使用する場合


前述したように、オプティミスティックな同時実行性の主な利点の1つは、システム・スループットを向上させることです。不要なブロックなしでトランザクションを同時に操作できるようにすることで、OCCはロックされたリソースの待機に要する時間を短縮します。これにより、特に競合レベルが比較的低い場合に、データベース・システムの効率と応答性が大幅に向上します。


さらに、OCCは悲観的な方法よりも優れた柔軟性を提供します。OCCでは、トランザクションが実行中ではなく変更のコミットを試行する場合にのみ、競合が検出されます。競合が頻繁に発生しないか、データの一貫性に限られた影響を及ぼす場合、このアプローチは、共有リソースのロックおよびロック解除に関連する不要なオーバーヘッドを回避するため、パフォーマンスを向上させることができます。


結論として、オプティミスティックな同時実行性制御は、スケーラビリティの向上や競合の削減など、多くの利点を提供しますが、欠点があります。その有効性は、アプリケーションのコンテキスト内の特定のユース・ケースおよびワークロードに大きく依存します。コンカレント操作を処理するデータベースまたはアプリケーションを設計する際に、これらの要因を慎重に検討することで、開発者は、この手法を採用するかどうかを十分な情報に基づいて決定できます。


悲観的同時実行性制御(PCC)


ペシミスティック同時実行性制御(PCC、ペシミスティック・ロックとも呼ばれる)は、同時データベース操作の処理に広く採用されています。これは、使用前にデータ項目のロックを取得することで、同時トランザクション間の競合を回避することを目的としています。この手法は、競合が発生する可能性が高いため、慎重なアプローチを取ることを前提としています。データの一貫性は保証されますが、悲観的な同時実行性制御には独自の課題セットが付属しています。


悲観的同時実行性制御の主な課題の1つは、ロック競合によるレイテンシの増加の可能性です。複数のトランザクションが同じデータ・アイテムのロックを保持している場合、このアイテムへのアクセスを必要とする他のトランザクションは待機する必要があり、その結果、パフォーマンスが低下します。さらに、ロックを解放する前にトランザクションが失敗したり終了したりすると、競合するトランザクションが無期限に互いのリソースを待機するデッドロックが発生する可能性があります。


これらの課題にもかかわらず、PCCにはその強みがあります。読取り操作と書込み操作間の競合を防止し、トランザクション間の厳密な分離レベルを確保することで、シリアライズ可能性が保証されます。また、同時実行性の高いシナリオでは、明示的なリソース・ロックおよび予測可能な動作が可能です。アプリケーション要件を慎重に管理し、考慮することで、悲観的な同時実行性制御によって、データベース操作を効率的に処理し、同時性の高い環境でデータの整合性を維持できます。


注: 完璧さはテクノロジーを議論するときの神話です。トレードオフは常に必要であるためです。たとえば、最高のパフォーマンスとスケーラビリティを必要とする人は、多くの場合、一貫性と整合性を損なう必要があります。パフォーマンス、スケーラビリティ、可用性および一貫性も、様々な障害シナリオ(インスタンス障害と大規模な停電など)など、特定のアプリケーションおよびユース・ケースのコンテキストで定期的にスコープ指定されます。テクノロジのコストメリットを常に評価し、ビジネス・ニーズ(SLA - サービス・レベル合意、RTO - リカバリ時間目標およびRPO - リカバリ・ポイント目標)および全体的な要件ごとに正しいものを決定する必要があります。


前述のように、PCCメソッドでは、データの整合性を保護するためにトランザクションにロックが導入されるため、その中のロックのタイプは何ですか。


PCCを使用する主な2種類のロック・タイプは次のとおりです。


  • 共有ロック- 変更(更新)される読み取りデータの書き込み操作をブロックするために使用されるロック。これらのロックは、他の読み取り操作には影響しません。
  • 排他ロック- 読み取り操作と書き込み操作の両方をブロックし、すべてのトランザクションを順番に実行させるロック。


悲観的な同時実行性制御の利点:


  • 統合データベースのサポート(アプリケーションではなく、データベースが同時実行性制御を管理します)。
  • トランザクションの開始時に競合をブロックします。
  • 読み取り操作と書き込み操作の競合を防止します。
  • トランザクション間の厳格な分離レベルを確保する。
  • シンプルで簡単に実装できます。


悲観的同時実行性制御の一貫性:


  • ロック時間が長い場合、パフォーマンスの問題が発生する可能性があります。
  • デッドロックが発生する可能性があります。アプリケーションおよびデータモデルを正しく実装する必要があります。
  • アプリケーションのスケーラビリティは制限される場合があります。
  • ボード上のデータベースではサポートされていません。
  • ロックおよびダウンタイムにより、リソース消費が高くなる場合があります。
  • ステートレス・モデルでは使用できません。


悲観的同時実行性制御の実装


データ項目にロックをかけることで、PCCは、トランザクションが特定のプロトコルに従っている場合に競合が発生しないことを保証します。ただし、この方法では、トランザクションがほかのプロセスによってロックが解放されるのを待つ必要があるため、システムパフォーマンスが低下することがあります。


PCCを使用する際のもう1つの重要な考慮事項はデッドロックです。2つ以上のトランザクションが互いがロックを解放するのを待機し、さらに続行できない状況です。デッドロックの検出と解決に対処することで、システムの複雑さが増し、慎重な設計の選択が必要になります。


PCCを実装すると、共有リソースへの競合するアクセスを防止することで、強力なデータ整合性が確保されます。ただし、開発者はパフォーマンスへの影響を慎重に評価し、潜在的なデッドロックを考慮して適切な設計上の意思決定を行う必要があります。


悲観的同時実行性制御を使用する場合


悲観的な同時実行性制御は、トランザクションの開始時に競合を防止するため、困難なデータ要件(複数のユーザーがアクセスするデータの同時操作)を持つアプリケーションに適しています。したがって、トランザクションは、多くのアプリケーションで問題となる可能性がある、相当な進捗を行った後にリコールする必要はありません。簡単に言えば、ロックを実装するコストがトランザクションを失う(ロールバック)よりも少ない場合は、悲観的な同時実行性制御が定期的に推奨されます。


別の観点から見ると、悲観的な同時実行性制御方法は、トランザクション・プロセス中にデータ・レコードが変更されないようにすることに重点を置いているため、選択したデータベースで、悲観的な同時実行性制御を有効にしてスケーリングする機能が統合されていることを確認する必要があります。たとえば、Oracle DatabaseにはReal Application Cluster (RAC)があり、拡張性と高可用性を確保するために長年にわたって進化してきましたが、組み込みの自動化により悲観的な同時実行性制御のメリットを引き続き提供しています。これは、特定のデータベースが両方を提供できる状況ですが、デプロイメントに関する複雑さがないわけではありません。結論として、アプリケーションには「ケーキを持ち、それを食べる」ことが求められます。


同時実行性制御メカニズムの選択


悲観的同時実行性制御と楽観的同時実行性制御を決定する際には、パフォーマンスと一貫性のバランスを取るトレードオフが必要です。オプティミスティックな同時実行性制御は、多くの場合、より高速であるとみなされます。データ整合性の競合が発生した場合にトランザクションを再起動する場合は、パフォーマンス・アクティビティが向上します。ペシミスティック同時実行性制御は、多数の更新があるアプリケーションや、アプリケーションを同時に使用して頻繁にデータを更新する(一貫性を維持する)アプリケーションに適しています。ペシミスティック同時実行性は、すべての競合を管理し、読取りと書込みの両方のデータの整合性を自動的に維持します。


そのため、競合の可能性が低い場合(複数のデータ・レコードがあるが、少数の同時ユーザーがある場合や、複数の読取り操作と組み合せて最小限の更新がある場合など)、またはトランザクションをロールバックする(失う)場合、オプティミスティック同時実行性制御は優れています。


ほとんどのDBMS (データベース管理システム)では、OCCまたはPCC(あるいはその両方)を使用してトランザクションを実行できます。使用中のデフォルトの同時実行性制御モードを常にチェックし、また、この組合せがアプリケーションの動作に重大な影響を与え、多くのビジネス目標に影響を及ぼす可能性があるため、使用中の分離をチェックしてください。


ANSI/ISO SQLで定義された4つのトランザクション分離レベルに関する前の記事の情報を補完すると、分離レベルによって1つのトランザクションが他の同時トランザクションの影響から分離される程度が決定されるため、トランザクション・シナリオの結果は使用される分離レベルに基づいて変更される可能性があることを理解することも不可欠です。


ANSI/ISO SQLによって定義される4つの分離レベルは、特定の分離レベルで許可される、または許可されない3つの状況によって影響を受ける可能性があります。


  • ダーティ・リード: トランザクションが別のコミットされていないトランザクションが変更されたデータを読み取る場合に発生します。これにより、データの整合性が損なわれ、外部キーに違反し、一意の制約が無視されるため、一貫性がなく誤った結果になる可能性があります。
  • 非反復読取り: トランザクションがデータのセットを取得する場所であり、同じデータを再度取得しようとすると、別のトランザクションが変更または削除されたことが検出され、潜在的なデータ整合性の問題が発生します。
  • ファントム読取り: トランザクションが特定の条件を満たす行のセットを読み取る場合に発生します。それでも、トランザクションが後で同じ行セットを再度読み込もうとすると、その条件は満たされなくなります。たとえば、別のユーザーが新しいデータを追加すると、トランザクション問合せ基準を満たすデータが増えます。


以下では、各SQL分離レベルと、前述の状況のいずれかの発生を許可するかどうかに基づいてマトリックス表を確認できます。

The 4 Isolation Levels

Dirty Reads (1)

Non-repeatable Reads (2)

Phantom Reads (3)

READ UNCOMMITTED

Permitted

Permitted

Permitted

READ COMMITTED

--

Permitted

Permitted

REPEATABLE READ

--

--

Permitted

SERIALIZABLE

--

--

--

 


SQL標準は、特定のロック・スキームを適用したり、特定の動作を義務付けたりしないことに注意してください。かわりに、前述の状況に対するこれらの分離レベルについて説明し、多くの異なるロック/並行性メカニズム(OCCやPCCなど)が存在できるようにします。



Oracleの継続的なイノベーション、継続的な取り組み


Oracle Databaseの運用と保護をシンプルにするというミッションを継続して、最近リリースされた23cデータベースには、この記事のトピックに関連する2つの重要な新しいあまり知られていない機能が組み込まれており、次の点に注意してください。


優先度トランザクション:


優先度トランザクションは、優先度が高いトランザクションをブロックする行ロックを保持する、優先度が低いトランザクションの中断を自動化します。


仕組み:


  • 新しいパラメータは、ユーザー・トランザクションの優先度(HIGH、MEDIUM、LOW)を設定します。
  • ユーザーは、行ロックを保持している優先度の低いトランザクションを中断する前に、トランザクションが待機する最大時間を構成できます。


利点:


  • DBAの管理負担を軽減します。
  • 優先度の高いトランザクションのレスポンス時間とトランザクション・スループットを維持します。



ロックフリー列値の予約:


ロックフリー予約を使用すると、複数のトランザクションで同じ列値に対して次のような予約を行うことができます。




たとえば、ショッピング・アプリは、他の買物客がアイテムを購入できないようにすることなく、アイテムがショッピング・バスケットに入れられるときに、アイテムの在庫を予約できます。


  • カラム値に対する更新は、ロックフリー予約として扱われ、将来値を変更することを意図しています。
  • 値を含む行は、コミット時にのみロックおよび更新されます。
  • データベースでは、数量が事前定義の制限を超えるまで、すべての予約済の更新が適用されます。

https://blogs.oracle.com/maa/post/fundamentals-of-reliability-distributed-databases-part-1



まとめ


楽観的な並行性制御を見ると、実用的で信頼性の高いシステムが見られます。これは、「反復可能読取り」分離レベルなどの緩い分離レベルではうまく機能します。ただし、悲観的な同時実行性制御とは異なり、ファントム読取りなどの問題が発生する可能性があります。オプティミスティックな同時実行性制御では、潜在的な読取りおよび書込みの競合を管理するようにアプリケーションを設計する必要があるため、開発作業が大幅に増える可能性があります。最も一般的な競合タイプは次のとおりです。


  • 読取り/書込みの競合: トランザクションAが行内のデータを読み取ると、別のトランザクション(B)が同じ行内のデータを変更するか、行内のデータを更新してから、トランザクションAが同じ行内のデータを読み取ります。この場合、トランザクションAによって読み取られるデータは異なります。このタイプの競合は、繰り返し不可能なダーティー読み取りにつながる可能性があります。
  • 書込み- 読取りの競合: このタイプの競合の原因は読取り- 書込みの競合と同じであり、ダーティ読取りが発生する可能性があります。
  • 書込みと書込みの競合は、2つの操作が順番にオブジェクトへの書込みを試行したときに発生します。後者の操作の結果は、最終的な書き込み結果を決定し、更新が失われる可能性があります(失われた更新の謎)。


たとえば、オプティミスティック同時実行性制御を使用するデータ・システムが、コミットが試行された時点で定期的に発生するOptimisticLockExceptionを捕捉したときに、リコールまたはロールバックが行われる状況です。現在実行中のトランザクションによって行われたすべての作業は、これが発生すると失われます。多くの場合、アプリケーションには、後で再試行するようにユーザーに要求する以外に選択肢はありません。


競合が増えると、トランザクションが失敗する可能性が高くなります。繰返しとロールバックでは、トランザクションが消失したために、このようなシステムのコストがビジネスに依存します。中断および消失したトランザクションを再試行するよう求められた場合と同様に、ユーザーは、アプリケーションがこれらの状況に対処するために明示的に設計されていないと想定する場合があります。また、この方法を使用するデータ・システムは、多くの場合、補正する表の行および索引レコードに依存します。したがって、最良の選択肢は、前の項で示したように、アプリケーションの要件に適合する適切な同時実行性制御を使用することです。


次の手順


これは、いくつかの興味深い新興技術について議論する前に重要な概念を明確にする2番目の記事です。次の記事では、「光の速度」のシナリオと、データの整合性、可用性、リカバリ性への影響について説明します。


コメント

このブログの人気の投稿

Oracle RACによるメンテナンスのためのドレインとアプリケーション・コンティニュイティの仕組み (2023/11/01)

Oracle Cloud Infrastructure Secure Desktopsを発表: デスクトップ仮想化のためのOracleのクラウドネイティブ・サービス (2023/06/28)

Oracle Cloudのデータベースをオブジェクト・ストレージにバックアップする3つの方法 (2021/12/13)