web-dev-qa-db-ja.com

グローバル一時テーブルで保持されているロックの種類は?

私は次のことを考えています:

  • 分離レベルはRead Committedです。
  • データの挿入、削除、または読み取り

従来の行ストアテーブルと同じグローバルテンポラリテーブルで使用されるロック(読み取り用に共有され、挿入/削除用に排他的)です。

一時テーブルの場合、現在のコンテキストで「存続」するため、ブロックは発生しないと思います。そのため、データの読み取りと挿入を同時に行うことはできません。

しかし、グローバル一時テーブルの場合、多くの操作があるとしましょう。新しいデータを挿入する操作、データを削除する操作、データを読み取ろうとする操作は削除されます。

テーブルの構造が次のとおりだとします。

GroupID EntityID
1       101
1       102
1       103
2       101
2       104
3       100

同じルール はここに適用されますか?

2
gotqn

私はこの質問に興味があり、tempdbが特別なデータベースであるか、またはデフォルトの分離「Read Committed」が適用されている別のユーザーデータベースと同じであるかを確認したいと思いました。

以下は私が実行したクエリです:

--Created two tables in tempdb, one named table and second one as gobal tempdb table

select * into tempdb.dbo.msgs from sys.messages


select * into ##msgs from sys.messages

次のウィンドウでこれらのテーブルのいくつかのレコードに対して実行された更新クエリ

begin tran
go
update dbo.msgs set language_id = 1055 where message_id = 11242
go
update ##msgs set language_id = 1055 where message_id = 11242
go

上記の両方のステートメントで、予想どおり22行が更新されました。

後で、私は2つの異なるウィンドウでこれら2つのテーブルに対してselectステートメントを実行しましたが、これまでのところ両方ともスタックしています。

First Select Query

Second Select Query

最初のクエリでは画面にレコードがまったく表示されないのに対し、2番目のケースでは、8830レコードが画面に表示され、その後スタックします(理由は不明ですか?)。彼らは更新が完了するのを待っています。これは、MSSQLデータベースのデフォルトの動作で想定されていたものです。

私はsp_whoisactiveを使用して同じことを検証し、以下のようにデータベースのブロックがあることがわかりました。

Output of sp_whoisactive

詳細については、それぞれのロック情報を示します。

第一:

<Database name="tempdb">
  <Objects>
    <Object name="msgs" schema_name="dbo">
      <Locks>
        <Lock resource_type="OBJECT" request_mode="IS" request_status="GRANT" request_count="1" />
        <Lock resource_type="PAGE" page_type="*" request_mode="S" request_status="WAIT" request_count="1" />
      </Locks>
    </Object>
  </Objects>
</Database>

2番目:

<Database name="tempdb">
  <Objects>
    <Object name="##msgs" schema_name="dbo">
      <Locks>
        <Lock resource_type="OBJECT" request_mode="IX" request_status="GRANT" request_count="1" />
        <Lock resource_type="PAGE" page_type="*" request_mode="UIX" request_status="GRANT" request_count="22" />
        <Lock resource_type="RID" page_type="*" request_mode="X" request_status="GRANT" request_count="22" />
      </Locks>
    </Object>
    <Object name="msgs" schema_name="dbo">
      <Locks>
        <Lock resource_type="OBJECT" request_mode="IX" request_status="GRANT" request_count="1" />
        <Lock resource_type="PAGE" page_type="*" request_mode="UIX" request_status="GRANT" request_count="22" />
        <Lock resource_type="RID" page_type="*" request_mode="X" request_status="GRANT" request_count="22" />
      </Locks>
    </Object>
  </Objects>
</Database>

3番目:

<Database name="tempdb">
  <Objects>
    <Object name="##msgs" schema_name="dbo">
      <Locks>
        <Lock resource_type="OBJECT" request_mode="IS" request_status="GRANT" request_count="1" />
        <Lock resource_type="PAGE" page_type="*" request_mode="S" request_status="WAIT" request_count="1" />
      </Locks>
    </Object>
  </Objects>
</Database>

また、以下のコマンドを使用して、これらの各トランザクションの分離レベルをクロスチェックしました。

SELECT CASE transaction_isolation_level 
WHEN 0 THEN 'Unspecified' 
WHEN 1 THEN 'ReadUncommitted' 
WHEN 2 THEN 'ReadCommitted' 
WHEN 3 THEN 'Repeatable' 
WHEN 4 THEN 'Serializable' 
WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL 
FROM sys.dm_exec_sessions 
where session_id in(63,66,67)

結果:

Isolation Level

これらすべてについて、tempdbの場合も、分離レベルは「コミットされた読み取り」として設定され、 rules は他のデータベースと同様に適用されます。

これらのクエリをMSSQL 2019バージョンで実行しました。

2