17.00 - 17.05 - デ-タベ-ス ロック、2フェーズ ロック、および逐次性 - Advanced SQL Engine - Teradata Database

Teradata Vantage™ - SQLリクエストおよびトランザクション処理

Product
Advanced SQL Engine
Teradata Database
Release Number
17.00
17.05
Published
2020年6月
Content Type
プログラミング リファレンス
ユーザー ガイド
Publication ID
B035-1142-170K-JPN
Language
日本語 (日本)

データベース ロックの定義

ロックは通常セマフォの形式で実装されるデバイスであり、リレーショナル データベース管理システムはこれを使用して、複数の並行セッションで実行する相互に同時発行されたトランザクションにより、データベース オブジェクトへの並列アクセスを管理します。データベース ロックに含まれる情報には、ロックしているデータベース オブジェクトの識別、それを保持しているトランザクションの識別、およびそのレベルと重大度があります。

データベース ロックのレベルと重大度は、要求したロックの対象となるオブジェクトが、それらのオブジェクト上で並行して実行している他のトランザクションによる変更から望ましいレベルで隔離されることについての、トランザクションに対する保証として考えることができます。

データベース ロックは、テーブル全体、個々の行パーティション内の個々のハッシュ値、または個々の行ハッシュ値のいずれかに加えて、行パーティション テーブルの個々の行パーティションに設定することができます。

2フェーズ ロックの定義

ロック プロトコルは、すでに保持しているロックを解放した後にトランザクションで追加のロックを要求しない場合に、2フェーズであると定義されます。このロック プロトコルは、逐次性の基礎となります。

2フェーズは次のとおりです。
  • データベース オブジェクトに対するロックが取得される拡張フェーズ。
  • 以前に取得されたロックが解放される縮小フェーズ。

これは、2フェーズ ルールと呼ばれることもあります。

実際には、トランザクションがコミットするかロールバックが終了した時点で縮小段階が発生します。この時点で、すべてのデータベース ロックは解放されます。

Host Utility(HUT)ロックは、Archive/Recoveryユーティリティおよび関連するさまざまなコマンドによって設定されるロックです。システムによって自動的に解放されるデータベース ロックとは異なり、HUTロックは、Archive/Recovery関連のユーティリティ コマンドでRELEASE LOCKオプションを明示的に指定した場合、またはArchive/Recovery関連の操作完了後にジョブがRELEASE LOCKユーティリティ コマンドを正常に実行依頼した場合にのみ解放されます。HUTロックの詳細については、<Teradata® Archive/Recovery Utilityリファレンス、B035-2412>を参照してください。

2PLが回避する主要な並列性の問題は、従来からあるトランザクション処理の問題が合成されたものです。通常は次のように呼ばれます。
  • 更新の消失の問題
  • コミットされない従属性の問題。
  • 不整合な分析の問題
  • ダーティ読み取りの問題。
  • デッドロックの問題(デッドロックおよびプロキシ ロックを参照)。
さらに以下の問題も発生する可能性があります。
  • ロック管理のためのシステム オーバーヘッドの増大
  • 並列性の減少

    ロックにより導かれる低位並列性の影響は、複数のレベルのロック粒度をサポートするTeradata Databaseのようなシステムでは大幅に減少します。

これらの同時並行性の問題の詳細について、一般的なトランザクション処理のテキストブックを参照してください。

逐次性の定義

複数のトランザクションをどのような順序で続けて実行してもデータベースの保全性が保たれるような、トランザクションによる並列データベース アクセスの特性は、逐次性と呼ばれます。逐次性についての次の定義も同等です。ある複数のトランザクションのセットが並列に実行されますが、セット内の各トランザクションTから見ると、他のメンバー トランザクションはTの前かTの後に実行され、その両方で実行されることはありません(GrayとReuter、1993を多少言い換えたもの)。

テンポラル テーブルの一部のDML操作では、逐次性違反が発生する可能性があります。詳細と回避方法については、<Teradata Vantage™ - テンポラル テーブル サポート、B035-1182>を参照してください。

Teradata Databaseは、セッションの現行の分離レベルがSERIALIZABLEである限り、非テンポラル トランザクションの逐次性を保証します(詳しくは、トランザクションのACIDプロパティおよび<Teradata Vantage™ - SQLデータ定義言語-構文規則および例、B035-1144>の「SET SESSION CHARACTERISTICS文」を参照)。

例えば、table_Aは当座預金口座のテーブルで、テーブルBは普通預金口座のテーブルであると想定します。あるトランザクションTx1は、400.00 USDを銀行顧客の当座預金口座から同じ顧客の普通預金口座に移動する必要があるとします。並列に実行している別のトランザクションTx2は、同じ銀行顧客に対してクレジット チェックを実行するとします。

例えで表わすために、次のテーブルに示す2つの口座に関する3つの状態を想定します。

状態 当座預金口座の残高 普通預金口座の残高
1 $900.00 $100.00
2 $500.00 $100.00
3 $500.00 $500.00
  • 状態1は、これらの口座の初期状態を示します。
  • 状態2は、中間の状態を示します。

    Tx1は$400.00を当座預金口座から引き出しましたが、その資金をまだ普通預金口座に預け入れていません。

  • 状態3は、これらの口座の最終状態を示します。

    Tx1は、当座預金口座から引き出された$400.00を普通預金口座に預け入れました。

2フェーズ ロックがなければ、Tx2は状態2での2つの口座を読み取り、クレジット チェックの実行可能性を判断して購買許可を正当化するには、残高が少なすぎると結論することがあります。しかし実際には、この顧客は2つの口座に$1000を所有しているので許可されるべきです。

これはダーティ読み取り現象の例です。

2PLが保証する状態は逐次性です。逐次性が実施されているとき、並列に実行しているこれらの非テンポラル トランザクションの結果は、それらが1つずつ続けて実行された場合と同じになります。

次の2つの可能性があります。

  1. Tx1が実行する。
  2. Tx2が実行する。

    このシナリオでは、Tx2は状態3だけを見るので、顧客はクレジット チェックに合格します。

  1. Tx2が実行する。
  2. Tx1が実行する。

    このシナリオでは、Tx2は状態1だけを見るので、顧客はクレジット チェックに合格します。

たとえ分散システムであっても、すべての場所で順序が同じでありどちらの結果もデータベースの一貫した状態になるのであれば、実際に行なわれるのがどちらのシナリオであっても違いはありません。ここから理解する必要のある重要な事柄は、逐次性が保証するのはデータベースの一貫した状態だけであり、トランザクション実行の特定の順序ではないということです。

データベース オブジェクトの2フェーズ ロックは、非テンポラル トランザクションの逐次性を保証するために十分ですが必要ではありません。

逐次化可能という用語は、元々は独立性として知られるACID特性の同義語ですが(トランザクションのACIDプロパティ、および<Teradata Vantage™ - SQLデータ定義言語-構文規則および例、B035-1144>の<SET SESSION CHARACTERISTICS文>を参照)、ANSI SQL規格での独立性という用語の用途は、分離レベルの概念が含まれるように広げられているので、逐次化可能な同義語ではなくなっています。

逐次性は正しいトランザクション スケジュールについて表わします。これは、データベースに対する影響が任意の連続的なスケジュールと等しいスケジュールのことです。

分離レベルの定義

分離レベルは、同時実行トランザクション、およびシステムがそれぞれのトランザクションを処理する際にお互いに更新を保護する程度に関する概念です。 ANSI SQL規格は、それがトランザクションの4つの分離レベルと呼ぶものを形式化します。 正確には、規格のこのセクションはSERIALIZABLEおよび禁止された特定の操作シーケンスの発生を許可する、3つのより弱い非逐次化の分離レベルを定義しています。

この規格では、禁止された操作シーケンスを集合的に望ましくない現象と呼びます。すべての商用RDBMSはロックを使用するトランザクション独立性を実装していますが、ANSIの分離レベルは、ロックに関してではなくこれらの現象に関して定義されていることに注意してください。

定義された望ましくない現象は、ダーティ読み取り、反復不可読み取り、およびファントム読み取りです。

ANSIが定義する非逐次化の分離レベルは、以下のとおりです。
  • 非コミット読み取り
  • コミット済み読取り
  • 再読込み可能読取り

次のテーブルは、異なる分離レベルと禁止されているさまざまな読み取り現象とのリレーションシップを示しています。

分離レベル ダーティ読み取り 反復不可読取り ファントム読み取り
非コミット読み取り 可能性あり 可能性あり 可能性あり
コミット済み読取り 可能性なし 可能性あり 可能性あり
再読込み可能読取り 可能性なし 可能性なし 可能性あり
逐次化可能 可能性なし 可能性なし 可能性なし

Teradata Databaseは、分離レベルのREAD COMMITTEDおよびREPEATABLE READをサポートしません。

READ UNCOMMITTED分離レベルはACCESSレベル ロックを使用して実装されます(Vantageのロック レベルと重大度のLock Severityテーブルの"ACCESS"エントリおよび<Teradata Vantage™ - SQLデータ定義言語-構文規則および例、B035-1144>の"SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL"を参照)。

Teradata Databaseは、行のバージョン管理の使用を有効にする、ロード分離と呼ばれる分離形式をサポートしています。Teradataは、基となるテーブルが変更されている最中でも、コミットされている行の同時読み取りを許可します。ロード分離現象は、コミット済み読み取り分離レベルと互換性がありますが、通常のトランザクション境界に制限されていません。現象は、ロードがコミットされるまで持続し、ロード分離テーブルでのみ発生する可能性があります。LOAD COMMITTEDロッキング修飾子を使用する問合わせはACCESSロックのみを取得し、したがって同時ロード分離書き込みを許可するため、反復不可読み取りまたはファントム読み取りが発生する可能性があります。同時実行セッションでロード コミットが発生した場合、同じトランザクション内で同じ問合わせが実行されると、読み取り側トランザクションは変更された行を見ることができます。これは、反復不可読み取りの現象です。さらに、新たにコミットしたデータが原因で同時実行ロード コミットで別のローが返された後に同じ問合わせの実行が検索条件とともに繰り返された場合に、ファントム読み取り現象が発生する可能性があります。

ロード分離の詳細については、ロード分離を参照してください。

読取り専用操作のトランザクション分離レベルの変更

パフォーマンスを向上させるために、トランザクションの独立性レベルを犠牲にすることもあります。これはデータを書き込む操作では無意味ですが、一貫していて信頼でき反復可能な結果を取得するよりも、データの一部の局面についての一般的な印象を取得することにだけ関心がある場合には特に、ダーティ読み取り操作を許可するために意味を持つこともあります。

これはとても重要な考慮事項であり、軽く考えるべき点ではありません。読取り専用操作をACCESSレベル ロッキングにするかどうかを決定する前に、セッション全体の質的なワークロードを注意深く検討しなければなりません。例えば、MultiLoad IMPORTジョブが実行中のセッションを考えてみましょう。MultiLoadが適用フェーズの際にテーブルの行を更新するときに(詳細は<Teradata® MultiLoadリファレンス、B035-2409>を参照)、適用フェーズ中にACCESSロックを使用してMultiLoadジョブのターゲット テーブルで問合わせを行なうと非常に不正確な結果セットが生成されることがあります。この場合、結果はおそらくテーブル データの適切な内容とは言えないものになってしまいます。

Teradata Databaseは、次の2つのレベルで可能性を許可するメソッドを提供します。それらは、個別リクエストおよびセッションです。

デフォルトの読取り専用ロック重大度を設定するレベル 使用するメソッド
個別リクエスト LOCKINGリクエスト修飾子。

このリクエスト修飾子の構文および使用法の詳細について、<Teradata Vantage™ - SQLデータ操作言語、B035-1146>を参照してください。

セッション SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL文。

この文の構文および使用法について詳しくは、<Teradata Vantage™ - SQLデータ定義言語-構文規則および例、B035-1144>を参照してください。

SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVELがREAD UNCOMMITEDに設定されている場合の読み取り操作のACCESSロックのグローバル適用は、DBS制御フィールドAccessLockForUncomReadの設定に依存します。

フィールドがFALSEに設定されている場合は、INSERT、DELETE、MERGE、およびUPDATEリクエスト内のSELECT操作がREADロックを設定しますが、フィールドがTRUEに設定されている場合は、同じSELECT操作がACCESSロックを設定します。詳細については、<Teradata Vantage™ - データベース ユーティリティ、B035-1102>および<Teradata Vantage™ - SQLデータ定義言語-構文規則および例、B035-1144>のSET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVELを参照してください。

ACCESSロックでの検索

ACCESSロックは、EXCLUSIVEロック以外のすべてのロック重大度と両立できるため、ACCESSロックを要求しているユーザーは、WRITEロックが設定されている、ダーティ読み取りと呼ばれる状況にあるオブジェクトへの読み取りが許されます。すなわち、WRITEロックを保持するアプリケーションがデータを変更している間に、ACCESSロックを保持するアプリケーションがその同じデータを同時に検索することができます。したがって、ACCESSロックを設定する問合わせでは、正しくないか、または矛盾した結果が返される可能性があります。

例えば、LOCKING FOR ACCESS句とともに、セカンダリ インデックスの制約を使用したSELECTリクエストを実行する場合を考えてみてください。

別のユーザーによってWRITEロックが設定されているオブジェクトに対してACCESSロックが許可されると、セカンダリ インデックス サブテーブルのキーが見つかってから、データ行が検索されるまでの間に、その列値が変わってしまう場合があります(SELECTのインデックスの制約条件が満たされていても、基準となるデータ行と対比してその条件が常に再チェックされるとは限らないため、このような変更が起こる可能性があります)。あとで取り消されるようなトランザクションによって瞬時にしかデータが変更されないような場合でも、この種の矛盾が発生する可能性があります。

ACCESSロックの読み取り操作に関する一般ポリシーでは、Teradata Databaseにより、ACCESSロックの読み取り操作時に更新中ではないすべての行が要求元に返されることが保証されます。更新中の行の場合は、おそらく矛盾した状態で行が返されるか、または返されません。

LOCKING FOR ACCESSの指定に関する考慮事項

通常、READロックは、SELECT操作のオブジェクトに設定され、そのオブジェクトがすでにWRITE用にロックされていると、そのリクエストは、待ち行列に入れられます。

アドホックな問合わせがデータの整合性に関係ない場合には、LOCKINGリクエスト修飾子を使用してデフォルトのREADロックをACCESSロックでオーバーライドすることができます。例えば、次のようになります。

    LOCKING TABLE tablename FOR ACCESS
    SELECT ...
    FROM tablename ...;

LOCKING FOR ACCESSの作用は書込み中の読取りであるため、このロックではダーティー読取りが発生するかもしれません。ACCESSロックを指定するための最良のアプローチは、詳細な結果が必要なときではなく、問題のデータに関する広範囲の統計的なスナップショットに関心があるときにのみ、それらを使用することです。ただし、ロード分離テーブルでは、テーブルで同時実行分離書き込みが同時に発生している場合でも、コミット済みのデータを取得するためにLOCKING FOR LOAD COMMITTEDが使用されることがあります。

以下の各点に詳しく述べられているように、ACCESSロックの結果として要求元に不正確または不整合なデータが返されることがあります。
  • ACCESSロックを伴うSELECTは、別のリクエストが同じオブジェクトを変更しているときでも、その対象のオブジェクトからデータを検索することができます。

    そのために、ACCESSロックを使用するリクエストからの結果は、矛盾したものになることがあります。

  • 矛盾した返答の可能性は、ACCESSロックを使用するリクエストが条件式の中でセカンダリ インデックス値を使用するときに特に高くなります。

    WRITE(書込み)のために保持されているオブジェクトでACCESSロックが認められた場合は、セカンダリ インデックスのサブテーブルが見つけられた時からデータ行が取り出される時までの間に、制約の値が変わることがあります。

    満たされたSELECTのインデックスの制約は、基本テーブルの行に対して二重にチェックされていないために、このように変わる可能性があります。

LOCKING ROWリクエスト修飾子を使用して、複数行ハッシュをロックすることはできません。複数行ハッシュでLOCKING ROW FOR ACCESSを指定すると、宣言は暗黙的にLOCKING TABLE FOR ACCESSに変換されます。

LOCKINGリクエスト修飾子の使用例

矛盾した返答の可能性が特に高いのは、ACCESSリクエストが条件式の中でセカンダリ インデックス値を使用するときです。 満たされたインデックス制約は、検索されたデータ行に対して再チェックされないからです。

例えば、qualify_accntがセカンダリ インデックスとして定義されていると仮定すると、次のリクエストはリクエスト テキストの後に結果を返します。

    LOCKING TABLE accnt_rec FOR ACCESS
    SELECT accnt_no, qualify_accnt
    FROM accnt_rec
    WHERE qualify_accnt = 1587;
    Accnt_No  Qualify_Accnt
    --------  ------------
        1761          4214

この場合、値1587はセカンダリ インデックスのサブテーブルで見つかり、対応するデータ行が選択されて返されました。しかし、この選択が進行している間に、アカウント1761のデータが他のユーザーによって変更されました。

副次的にアボートされたトランザクションによってデータが瞬間的に変更または削除された場合でも、このような返答の可能性があります。

あとで取り消されたトランザクションによってデータが瞬間的に変更された場合でも、このような矛盾が発生することがあります。ロード分離テーブルについては、LOCKING FOR LOAD COMMITTED修飾子を使用すると、そのような一貫性のない部分を防ぐことができることに注意してください。LOCKING FOR LOAD COMMITTEDリクエスト修飾子と<Teradata Vantage™ - SQLデータ操作言語、B035-1146>を参照してください。