SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

SQL Server のゴーストクリーンアップタスクの基本動作 その 2

leave a comment

SQL Server のゴーストクリーンアップタスクの基本動作を見てみる その 1 の続きになります。

■ゴーストクリーンアップタスクによるレコードの変更を見てみる


前回の投稿で、ゴーストクリーンアップタスク (GhostCleanupTask) の実行時にはメモリ上の情報が以下のようになるという事を書きました。
image

[is_modified = 1] になるという事はページに変更がかかっているという事になります。
それでは、DELETE → ゴーストクリーンアップタスク でどのような変更がかかるかを見てみます。

DELETE をする前はこのようになっています。

BUFFER:

bstat = 0x9

PAGE HEADER:

m_lsn = (1385:26315:83)
m_slotCnt = 5
m_ghostRecCnt = 0

Allocation Status

GAM (1:2) = ALLOCATED              
SGAM (1:3) = NOT ALLOCATED         
PFS (1:24264) = 0x40 ALLOCATED   0_PCT_FULL                             
DIFF (1:6) = CHANGED
ML (1:7) = NOT MIN_LOGGED 

 

DATA:

Slot 0, Offset 0x60, Length 1607, DumpStyle BYTE
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 1607

Slot 1, Offset 0x6a7, Length 1607, DumpStyle BYTE
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 1607

Slot 2, Offset 0xcee, Length 1607, DumpStyle BYTE
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 1607

Slot 3, Offset 0x1335, Length 1607, DumpStyle BYTE
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 1607

Slot 4, Offset 0x197c, Length 1607, DumpStyle BYTE
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 1607

OFFSET TABLE:

Row – Offset                       

4 (0x4) – 6524 (0x197c)            
3 (0x3) – 4917 (0x1335)            
2 (0x2) – 3310 (0xcee)             
1 (0x1) – 1703 (0x6a7)             
0 (0x0) – 96 (0x60)                

今回は、[bstat] という情報も併せて記載しています。
この項目ですがメモリ内でデータがどのような状態となっているかをビットで表しています。

bstat の種類は以下のクエリで確認できます。

SELECT
    map_value, map_key
FROM
    sys.dm_xe_map_values
WHERE
    name = N’bstats_bits’
ORDER  BY
    map_key

種類としては以下のようなものがあります。

image

今回の対象となりそうなものだと以下の組み合わせでしょうか。

— 0x14b : CHKGEN + DONT_IGNORE + HASHED + DIRTY + ONLRU
— 0x10b : CHKGEN + HASHED + DIRTY + ONLRU
— 0x109 : CHKGEN + HASHED + ONLRU
— 0x4b  : DONT_IGNORE + HASHED + DIRTY + ONLRU
— 0xb   : HASHED + DIRTY + ONLRU
— 0x9     : HASHED + ONLRU

DELETE → CHECKPOINT を実行するとこのようになります。
DELETE によってゴーストレコードとなりますが、オフセット情報 (どこからどこまでがスロットの区切りとなるのか) は変更されていないですね。

BUFFER:

bstat = 0x109

PAGE HEADER:

m_lsn = (1386:7568:33)
m_slotCnt = 5
m_ghostRecCnt = 5

Allocation Status

GAM (1:2) = ALLOCATED              
SGAM (1:3) = NOT ALLOCATED         
PFS (1:24264) = 0x48 ALLOCATED   0_PCT_FULL                             
DIFF (1:6) = CHANGED
ML (1:7) = NOT MIN_LOGGED          

DATA:

Slot 0, Offset 0x60, Length 1607, DumpStyle BYTE
Record Type = GHOST_DATA_RECORD     Record Attributes =  NULL_BITMAP    Record Size = 1607

Slot 1, Offset 0x6a7, Length 1607, DumpStyle BYTE
Record Type = GHOST_DATA_RECORD     Record Attributes =  NULL_BITMAP    Record Size = 1607

Slot 2, Offset 0xcee, Length 1607, DumpStyle BYTE
Record Type = GHOST_DATA_RECORD     Record Attributes =  NULL_BITMAP    Record Size = 1607

Slot 3, Offset 0x1335, Length 1607, DumpStyle BYTE
Record Type = GHOST_DATA_RECORD     Record Attributes =  NULL_BITMAP    Record Size = 1607

Slot 4, Offset 0x197c, Length 1607, DumpStyle BYTE
Record Type = GHOST_DATA_RECORD     Record Attributes =  NULL_BITMAP    Record Size = 1607

OFFSET TABLE:

Row – Offset                       
4 (0x4) – 6524 (0x197c)            
3 (0x3) – 4917 (0x1335)            
2 (0x2) – 3310 (0xcee)             
1 (0x1) – 1703 (0x6a7)             
0 (0x0) – 96 (0x60)                

 

それでは DBCC FORCEGHOSTCLEANUP を実行します。

BUFFER:

bstat = 0x10b

PAGE HEADER:

m_lsn = (1388:23855:114)
m_slotCnt = 1
m_ghostRecCnt = 1

Allocation Status

GAM (1:2) = ALLOCATED              
SGAM (1:3) = NOT ALLOCATED         
PFS (1:24264) = 0x8   0_PCT_FULL
DIFF (1:6) = CHANGED               
ML (1:7) = NOT MIN_LOGGED          

DATA:

Slot 0, Offset 0x197c, Length 1607, DumpStyle BYTE
Record Type = GHOST_DATA_RECORD     Record Attributes =  NULL_BITMAP    Record Size = 1607

OFFSET TABLE:

Row – Offset                       
0 (0x0) – 6524 (0x197c)            

1 レコードはゴーストレコードとして残ってしまっているのですが、それ以外のレコードは削除されていることが確認できます。

また、bstat は 0x10b となっています。
これは CHKGEN + HASHED + DIRTY + ONLRU となります。
DIRTY はダーティーページですので、ゴーストクリーンアップタスクの変更もダーティーページが発生していることが確認できます。
CHECKPOINT が発生したタイミングで現在のページの内容がデータファイルに変更されるのでデータファイルに対しての WRITE が発生していたようですね。

 

■ゴーストクリーンアップタスクで削除されなかったレコードについて考えてみる


それでは、削除されなかったレコードについて考えてみたいと思います。

まずは DELETE → CHECKPOINT 直後の IAM (Index Allocation Map) を見てみます。

IAM: Extent Alloc Status Slot 1 @0x000000001638A0C2

(1:0)        – (1:608)      = NOT ALLOCATED                             
(1:616)      – (1:664)      =     ALLOCATED                             
(1:672)      – (1:1120)     = NOT ALLOCATED                             
(1:1128)     – (1:1176)     =     ALLOCATED                             
(1:1184)     – (1:1632)     = NOT ALLOCATED                             
(1:1640)     – (1:1648)     =     ALLOCATED                             
(1:1656)     – (1:155544)   = NOT ALLOCATED                             
(1:155552)   -              =     ALLOCATED                             
(1:155560)   – (1:156064)   = NOT ALLOCATED                             
(1:156072)   – (1:156168)   =     ALLOCATED                             
(1:156176)   – (1:156576)   = NOT ALLOCATED                             
(1:156584)   – (1:157048)   =     ALLOCATED                             
(1:157056)   – (1:157088)   = NOT ALLOCATED                             
(1:157096)   – (1:157568)   =     ALLOCATED                             
(1:157576)   – (1:157600)   = NOT ALLOCATED                             
(1:157608)   – (1:157616)   =     ALLOCATED                             
(1:157624)   – (1:157816)   = NOT ALLOCATED                             

ALLOCATED (割り当て済み) のページが存在しているのが確認できますね。
ゴーストレコードとなってもレコードは存在していますので IAM としては対象のページは使用中として認識をしているようです。
# 厳密に言うと上記の値はページではなくエクステントをベースとして表示しているのですが。

それではゴーストクリーンアップタスクを実行して同じ情報を取得します。

IAM: Extent Alloc Status Slot 1 @0x000000001695A0C2

(1:0)        – (1:608)      = NOT ALLOCATED                             
(1:616)      – (1:624)      =     ALLOCATED                             
(1:632)      – (1:155544)   = NOT ALLOCATED                             
(1:155552)   -              =     ALLOCATED                             
(1:155560)   – (1:156576)   = NOT ALLOCATED                             
(1:156584)   -              =     ALLOCATED                             
(1:156592)   – (1:157816)   = NOT ALLOCATED                             

 

ALLOCATED となっている個所が減っていることが確認できます。
ゴーストクリーンアップタスクをを実行することで IAM から割り当てが解除されているのがここから確認ができます。

それでは割り当て中のページを DBCC PAGE でピンポイントで確認してみたいと思います。
今回はクラスタ化インデックスのリーフページである [156584] を確認してみました。

Slot 0, Offset 0x197c, Length 1607, DumpStyle BYTE

Record Type = GHOST_DATA_RECORD     Record Attributes =  NULL_BITMAP    Record Size = 1607

ゴーストレコードが残っているのが確認できますね。

今までは DBCC FORCEGHOSTCLEANUP という DBCC コマンドを使用してきましたが、[DBCC CLEANPAGE] という DBCC コマンドがあることをご存知でしょうか。

これは [sp_clean_db_file_free_space] や [sp_clean_db_free_space] というストアドプロシージャーで使用されている DBCC コマンドになります。

このコマンドのヘルプの注釈に以下の内容が記載されています。

テーブルからの削除操作や、行の移動を伴うような更新操作では、行への参照を削除することにより、直ちにページ上の領域が解放されます。
ただし、特定の状況下では、行が非実体レコードとして、物理的にデータ ページ上に残ってしまう場合があります。
非実体レコードは、バックグラウンド プロセスによって定期的に削除されます。
この残存データが、クエリへの応答としてデータベース エンジンから返されることはありません。
ただし、データまたはバックアップ ファイルの物理的なセキュリティに不安があるような環境では、sp_clean_db_free_space を使用することで、これらの非実体レコードをクリーニングすることができます。

このストアドを使うとゴーストクリーンアップタスクでも残ってしまったレコードをクリーニングすることができます。
ただし、リーフノードの 1 レコードはこれを実行してもクリーニングできないみたいなのですが…。

という事で今回はご紹介までという事で。

今回の投稿ではページを中心としてゴーストクリーンアップタスクを見てみました。
まだ書けていないことがいくつかありますが、長くなってきましたので続きは次の投稿で。

Written by masayuki.ozawa

4月 7th, 2011 at 8:22 pm

Posted in SQL Server

Tagged with

Leave a Reply

*