擬似テーブルは、それがテーブルわす物理テーブルの別名と見なすことができます(擬似という語はテーブルを修飾しており、ロックを修飾しているのではないことに注意してください)。疑似テーブルは、データ ディクショナリ行ハッシュ ロックを待ち行列に入れ、Teradataがデータ ディクショナリ行にロックを掛けるときに発生する可能性があるグローバル デッドロックを回避するメカニズムを提供します(デッドロックを参照)。
DDLがディクショナリ テーブルのプライマリおよびフォールバック両方の行ハッシュをロックする必要がある場合、システムは自動的に行ハッシュ レベル疑似テーブル ロックを掛けます。行ハッシュ レベル疑似テーブル ロックは意図的ロックと見なすことができます。つまり、それはリクエストがディクショナリ テーブルのプライマリおよびフォールバック両方に行ハッシュ ロックを掛けることを意図していることを示しています。
疑似テーブル ロックは、並列データベース体系における異なるAMPにあるプライマリおよびフォールバック両方の行に、行ハッシュの連続ロックを掛けられるようにします。疑似テーブル ロックを使用しないと、複数のユーザーが同時に、データ ディクショナリ テーブルのプライマリおよびフォールバック両方に行ハッシュ ロックを掛ける必要のあるDDLリクエストを実行した場合に、デッドロックが発生する可能性があります。複数のリクエストが並行して送信され、ディクショナリ テーブルの同じ行ハッシュをロックする必要がある場合、それらは行ハッシュを異なる順番で保持した状態で、プライマリおよびフォールバックAMPに到達する可能性があります。あるリクエストが最初にプライマリAMPで行ハッシュ ロックを取得し、別のものが最初にフォールバックAMPで取得することで、デッドロックが発生する場合があります。
- 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の両方のケースで、参照整合性制約がテーブルに定義されていると、追加の親、子、およびディクショナリ テーブルをロックする必要があるので、ロックがより複雑になります。ジャーナルやロックする必要がある他のディクショナリ テーブルなどが関与するオプションでは、さらに操作が複雑になります。