17.00 - 17.05 - 擬似テーブル ロック - 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
日本語 (日本)

擬似テーブルは、それがテーブルわす物理テーブルの別名と見なすことができます(擬似という語はテーブルを修飾しており、ロックを修飾しているのではないことに注意してください)。疑似テーブルは、データ ディクショナリ行ハッシュ ロックを待ち行列に入れ、Teradataがデータ ディクショナリ行にロックを掛けるときに発生する可能性があるグローバル デッドロックを回避するメカニズムを提供します(デッドロックを参照)。

DDLがディクショナリ テーブルのプライマリおよびフォールバック両方の行ハッシュをロックする必要がある場合、システムは自動的に行ハッシュ レベル疑似テーブル ロックを掛けます。行ハッシュ レベル疑似テーブル ロックは意図的ロックと見なすことができます。つまり、それはリクエストがディクショナリ テーブルのプライマリおよびフォールバック両方に行ハッシュ ロックを掛けることを意図していることを示しています。

疑似テーブル ロックは、並列データベース体系における異なるAMPにあるプライマリおよびフォールバック両方の行に、行ハッシュの連続ロックを掛けられるようにします。疑似テーブル ロックを使用しないと、複数のユーザーが同時に、データ ディクショナリ テーブルのプライマリおよびフォールバック両方に行ハッシュ ロックを掛ける必要のあるDDLリクエストを実行した場合に、デッドロックが発生する可能性があります。複数のリクエストが並行して送信され、ディクショナリ テーブルの同じ行ハッシュをロックする必要がある場合、それらは行ハッシュを異なる順番で保持した状態で、プライマリおよびフォールバックAMPに到達する可能性があります。あるリクエストが最初にプライマリAMPで行ハッシュ ロックを取得し、別のものが最初にフォールバックAMPで取得することで、デッドロックが発生する場合があります。

疑似テーブル ロックは、次のDDL文のさまざまなデータ ディクショナリ テーブルに、行ハッシュ レベルで掛けられます。
  • CREATE HASH INDEX
  • CREATE JOIN INDEX
  • CREATE TABLE
  • DROP HASH INDEX
  • DROP JOIN INDEX
  • DROP MACRO
  • DROP PROCEDURE
  • DROP TABLE
  • DROP VIEW

    これらのロックは、行ハッシュ レベル擬似テーブル ロックというよりも擬似行ハッシュ ロックと呼ぶ方が正確ですが、EXPLAIN句のテキストはこの規則に従っておらず、この説明はEXPLAIN句のテキストで使用されている用語に従います(EXPLAINリクエスト修飾子句の用語を参照)。

行ハッシュ レベル擬似テーブル ロック

このシナリオ一式では、単純なCREATE TABLEリクエストおよびDROP TABLEリクエストを使用して、Teradata Databaseが行ハッシュ レベルの擬似テーブル ロックを使用する方法を示します。

次の例は、テーブルt4の単純なCREATE TABLE定義のEXPLAINレポートです。

EXPLAIN CREATE TABLE t4 (a INTEGER, b INTEGER);
Explanation
------------------------------------------------------------------------------
  1) First, we lock DB1.T4 in TD_MAP1 for exclusive use.
  2) Next, we lock a distinct DBC."pseudo table" in
     TD_DATADICTIONARYMAP for read on a RowHash for deadlock prevention,
     we lock a distinct DBC."pseudo table" in TD_DATADICTIONARYMAP for
     write on a RowHash for deadlock prevention, and we lock a distinct
     DBC."pseudo table" in TD_DATADICTIONARYMAP for write on a RowHash
     for deadlock prevention.
  3) We lock DBC.AccessRights in TD_DATADICTIONARYMAP for write on a
     reserved RowHash in a single partition to prevent global deadlock.
  4) We lock DBC.DBase in TD_DATADICTIONARYMAP for read on a RowHash,
     we lock DBC.Maps in TD_DATADICTIONARYMAP for read on a RowHash, we
     lock DBC.TVFields in TD_DATADICTIONARYMAP for write on a RowHash,
     we lock DBC.Indexes in TD_DATADICTIONARYMAP for write on a RowHash,
     we lock DBC.TVM in TD_DATADICTIONARYMAP for write on a RowHash,
     and we lock DBC.AccessRights in TD_DATADICTIONARYMAP for write on
     a single partition.
  5) We execute the following steps in parallel.
       1) We do a single-AMP ABORT TEST step from DBC.DBase by way of
          the unique primary index "Field_1 = 'DB1'" with a residual
          condition of ("'00001904'XB= DBC.DBase.Field_2").
       2) We do a single-AMP ABORT TEST step from DBC.TVM by way of the
          unique primary index "Field_1 = '00001904'XB, Field_2 = 'T4'".
       3) We do an INSERT step into DBC.Indexes (no lock required).
       4) We do an INSERT step into DBC.TVFields (no lock required).
       5) We do an INSERT step into DBC.TVFields (no lock required).
       6) We do a two-AMP ABORT TEST step in TD_DATADICTIONARYMAP from
          DBC.Maps by way of unique index # 4 "Field_3 = 1025" with no
          residual conditions.
       7) We do an INSERT step into DBC.TVM (no lock required).
       8) We INSERT default rights to DBC.AccessRights for DB1.T4.
  6) We create the table header in TD_MAP1.
  7) Finally, we send out an END TRANSACTION step to all AMPs involved
     in processing the request.
  -> No rows are returned to the user as the result of statement 1.

CREATE TABLEがステップ1のテーブルにテーブル レベル ロックを適用する前にプロキシ ロックを掛けることはありません。テーブルは作成されるまで存在せず、その他のユーザーがアクセスしようとする可能性がないため、これは不必要です。

ステップ2では、擬似テーブル内の行ハッシュの1つの擬似ロックを1つのAMPに設定します。同じ行ハッシュに対するすべてのDDLリクエストがこの擬似テーブルを操作する必要があるので、プライマリとフォールバックの両方のコピーをロックしようとしてもデッドロックは発生しません。ステップ2は、全AMPロック ステップです。各AMPは、同じリストの行ハッシュ ロックを渡され、行ハッシュのアクティブなプライマリAMPのみがロックを掛けます。

ステップ3は、単一のパーティション上のAccessRights向けプロキシ ロックです。

ステップ4は、実際のDBase、Maps、TVField、Indexes、TVM、およびAccessRightsディクショナリ テーブルに行ハッシュ ロックを掛けます。ステップ4は、全AMPステップで、行ハッシュを持つプライマリおよびフォールバックAMPのみがロックを掛けます。

ステップ2で掛けられる行ハッシュ レベル ロックの数はステップ4より少ないことに注目してください。EXPLAINテキストは、ステップ4のどの行ハッシュ レベルのロックがステップ2のロックに対応するかを示しません。さらに、ロックの並べ替え方法はテーブル/行ハッシュの順序なので、ステップ2での行ハッシュ レベル ロックは、一致するREADロックおよびWRITEロックを基にしてステップ4と正確に同じ順序では掛けられません。ステップ2の場合、すべての行ハッシュのテーブルは同じですが、ステップ4の場合、各行ハッシュのテーブルは異なります。

DBC.TVFieldsおよびDBC.Indexesは同じプライマリ インデックスを持つため行ハッシュは両方のテーブルで同じになり、疑似テーブルで必要な行ハッシュ レベル ロックは1つのみであるため、ステップ2で掛ける行ハッシュ レベル ロックはステップ4よりも少なくなります。ただしステップ4では、個別のディクショナリ テーブル用のロックなので、2つの実際の行ハッシュ レベル ロックを掛ける必要があります。

次の例は、テーブルに対する権限がユーザーまたはデータベースに明示的に与えられていない場合の単純なDROP TABLEリクエストのEXPLAINレポートです。

EXPLAIN DROP TABLE t4;
Explanation
------------------------------------------------------------------------------
  1) First, we lock DB1.t4 in TD_MAP1 for exclusive use on a reserved
     RowHash to prevent global deadlock.
  2) Next, we lock DB1.t4 in TD_MAP1 for exclusive use.
  3) We lock a distinct DBC."pseudo table" in TD_DATADICTIONARYMAP for
     read on a RowHash for deadlock prevention, we lock a distinct
     DBC."pseudo table" in TD_DATADICTIONARYMAP for write on a RowHash
     for deadlock prevention, we lock a distinct DBC."pseudo table" in
     TD_DATADICTIONARYMAP for write on a RowHash for deadlock
     prevention, we lock a distinct DBC."pseudo table" in
     TD_DATADICTIONARYMAP for write on a RowHash for deadlock
     prevention, and we lock a distinct DBC."pseudo table" in
     TD_DATADICTIONARYMAP for write on a RowHash for deadlock
     prevention.
  4) We lock DBC.AccessRights in TD_DATADICTIONARYMAP for write on a
     reserved RowHash in a single partition to prevent global deadlock.
  5) We lock DBC.DBase in TD_DATADICTIONARYMAP for read on a RowHash,
     we lock DBC.TVFields in TD_DATADICTIONARYMAP for write on a
     RowHash, we lock DBC.Indexes in TD_DATADICTIONARYMAP for write on
     a RowHash, we lock DBC.TVM in TD_DATADICTIONARYMAP for write on a
     RowHash, we lock DBC.DBCAssociation in TD_DATADICTIONARYMAP for
     write on a RowHash, we lock DBC.RCEvent in TD_DATADICTIONARYMAP
     for write on a RowHash, we lock DBC.Dependency in
     TD_DATADICTIONARYMAP for write on a RowHash, we lock
     DBC.ObjectUsage in TD_DATADICTIONARYMAP for write on a RowHash,
     and we lock DBC.AccessRights in TD_DATADICTIONARYMAP for write on
     a single partition.
  6) We drop the table header and the data in the table DB1.t4.
  7) We execute the following steps in parallel.
       1) We do a single-AMP ABORT TEST step from DBC.DBase by way of
          the unique primary index "Field_1 = 'DB1'" with a residual
          condition of ("'00001904'XB= DBC.DBase.Field_2").
       2) We do a single-AMP ABORT TEST step from DBC.TVM by way of the
          unique primary index "Field_1 = '00001904'XB, Field_2 = 'T4'"
          with a residual condition of ("'0000470D0000'XB=
          DBC.TVM.Field_5").
       3) We do a single-AMP ABORT TEST step from DBC.TVM by way of the
          unique primary index "Field_1 = '00001904'XB, Field_2 = 'T4'"
          with a residual condition of ("DBC.TVM.Field_33 > 0").
  8) We lock DBC.StatsTbl in TD_DATADICTIONARYMAP for write on a
     RowHash.
  9) We execute the following steps in parallel.
       1) We do a single-AMP DELETE step in TD_DATADICTIONARYMAP from
          DBC.StatsTbl by way of the primary index "{LeftTable}.Field_2
          = '0000470D0000'XB" with no residual conditions.
       2) We do a single-AMP DELETE step in TD_DATADICTIONARYMAP from
          DBC.TVFields by way of the primary index "Field_1 =
          '0000470D0000'XB" with no residual conditions.
       3) We do a single-AMP DELETE step in TD_DATADICTIONARYMAP from
          DBC.Indexes by way of the primary index "Field_1 =
          '0000470D0000'XB" with no residual conditions.
       4) We do a single-AMP DELETE step in TD_DATADICTIONARYMAP from
          DBC.DBCAssociation by way of the primary index "Field_1 =
          '0000470D0000'XB" with no residual conditions.
       5) We do a single-AMP DELETE step in TD_DATADICTIONARYMAP from
          DBC.TVM by way of the unique primary index "Field_1 =
          '00001904'XB, Field_2 = 'T4'" with no residual conditions.
       6) We do a single-AMP DELETE step in TD_DATADICTIONARYMAP from a
          single partition of DBC.AccessRights by way of the primary
          index "Field_1 = '00001904'XB, Field_2 = '00001904'XB,
          Field_3 = '0000470D0000'XB" with a residual condition of (
          "DBC.AccessRights.Field_3 = '0000470D0000'XB") (no lock
          required).
       7) We do a single-AMP DELETE step in TD_DATADICTIONARYMAP from
          DBC.Dependency by way of the primary index "Field_1 =
          '0000470D0000'XB" with no residual conditions.
       8) We do a single-AMP DELETE step in TD_DATADICTIONARYMAP from
          DBC.ObjectUsage by way of the primary index "Field_1 =
          '00001904'XB, Field_2 = '0000470D0000'XB" with no residual
          conditions.
       9) We do an INSERT step into DBC.RCEvent.
10) We spoil the statistics cache for the table, view or query.
11) We end logging on DB1.t4.
12) We spoil the parser's dictionary cache for the table.
13) Finally, we send out an END TRANSACTION step to all AMPs involved
     in processing the request.
  -> No rows are returned to the user as the result of statement 1.

CREATE TABLEリクエストとは異なり、複数のユーザーがテーブルt4にアクセスまたはDROPを試行している可能性があるため、プロキシ ロックを使用して調整する、つまりステップ1で予約済み行ハッシュをロックし、次にステップ2でテーブルt4をロックする必要があります。

ステップ3では、擬似テーブル内の行ハッシュの1つの擬似ロックを1つのAMPに設定し、同じ行ハッシュに対するすべてのDDLリクエストがこの擬似テーブルを操作する必要があるので、プライマリとフォールバックの両方のコピーをロックしようとしてもデッドロックは発生しません。ステップ2は、全AMPロック ステップです。各AMPは、同じリストの行ハッシュ ロックを渡され、行ハッシュのアクティブなプライマリAMPのみがロックを掛けます。

ステップ4は、単一のパーティション上のAccesssRightsのプロキシ ロックです。

ステップ5は、ディクショナリ テーブルの実際のDBase、TVFieldsなどに行ハッシュ レベル ロックを掛けます。これは全AMPステップですが、そうであっても、該当ステップで言及されている特定の行ハッシュについては、その行ハッシュを所有するプライマリAMPおよびフォールバックAMPのみがロックを設定します。

このリクエストの場合、ステップ3で掛けられる行ハッシュ レベル ロックの数はステップ5で掛けられる数よりも少なくなります。EXPLAINテキストは、ステップ5のどの行ハッシュ レベルのロックがステップ3のロックに対応するかを示しません。さらに、ロックの並べ替え方法はテーブル/行ハッシュの順序なので、ステップ3の行ハッシュ レベル ロックは一致するREADロックおよびWRITEロックを基にしたステップ5と正確に同じ順序では設定されません。

DBC.TVFieldsおよびDBC.Indexesは同じプライマリ インデックスを持つため行ハッシュは両方のテーブルで同じになり、疑似テーブルで必要な行ハッシュ レベル ロックは1つのみであるため、ステップ3で掛ける行ハッシュ レベル ロックはステップ5よりも少なくなります。ただしステップ5では、個別のディクショナリ テーブル用のロックなので、2つの実際の行ハッシュ レベル ロックを掛ける必要があります。

CREATE TABLEとDROP TABLEの両方のケースで、参照整合性制約がテーブルに定義されていると、追加の親、子、およびディクショナリ テーブルをロックする必要があるので、ロックがより複雑になります。ジャーナルやロックする必要がある他のディクショナリ テーブルなどが関与するオプションでは、さらに操作が複雑になります。