sql >> データベース >  >> RDS >> Database

FGCB_ADD_REMOVEラッチ

    前回の記事では、ラッチとは何か、なぜ必要なのか、どのように機能するのかを説明することで、ラッチに関する新しいシリーズを開始しました。この記事の前に、その記事を読むことを強くお勧めします。この記事では、FGCB_ADD_REMOVEラッチについて説明し、それがボトルネックになる可能性があることを示します。

    FGCB_ADD_REMOVEラッチとは何ですか?

    ほとんどのラッチクラス名は、保護するデータ構造に直接関連付けられています。 FGCB_ADD_REMOVEラッチは、FGCBまたはファイルグループ制御ブロックと呼ばれるデータ構造を保護し、SQLServerインスタンスの各オンラインデータベースの各オンラインファイルグループにこれらのラッチの1つがあります。ファイルグループ内のファイルを追加、削除、拡大、または縮小するときは常に、EXモードでラッチを取得する必要があります。次に割り当てるファイルを特定するときは、ファイルグループの変更を防ぐために、SHモードでラッチを取得する必要があります。 (ファイルグループのエクステント割り当ては、ファイルグループ内のファイルを介してラウンドロビンベースで実行され、比例塗りつぶしも考慮に入れることに注意してください。 、ここで説明します。)

    ラッチはどのようにしてボトルネックになりますか?

    このラッチがボトルネックになる最も一般的なシナリオは次のとおりです。

    • 単一ファイルのデータベースがあるため、すべての割り当てはその1つのデータファイルから行う必要があります
    • ファイルの自動拡張設定は非常に小さく設定されています(SQL Server 2016より前は、データファイルのデフォルトの自動拡張設定は1MBでした)
    • スペースを割り当てる必要のある同時操作が多数あります(たとえば、多くのクライアント接続からの一定の挿入ワークロード)

    この場合、ファイルが1つしかない場合でも、割り当てが必要なスレッドは、SHモードでFGCB_ADD_REMOVEラッチを取得する必要があります。次に、単一のデータファイルから割り当てを試み、スペースがないことを認識してから、EXモードでラッチを取得して、ファイルを拡張できるようにします。

    8つの別々のスケジューラで実行されている8つのスレッドがすべて同時に割り当てようとし、ファイルにスペースがないことを認識しているため、ファイルを拡張する必要があると想像してみてください。彼らはそれぞれ、EXモードでラッチを取得しようとします。そのうちの1つだけがそれを取得でき、ファイルの拡張に進み、他のファイルは待機する必要があります。待機タイプはLATCH_EXで、リソースの説明はFGCB_ADD_REMOVEで、ラッチのメモリアドレスが追加されます。

    7つの待機中のスレッドは、ラッチの先入れ先出し(FIFO)待機キューにあります。ファイルの拡張を実行するスレッドが完了すると、ラッチが解放され、最初の待機中のスレッドに付与されます。ラッチのこの新しい所有者はファイルを拡大しに行き、ファイルがすでに拡大されており、何もすることがないことを発見します。そのため、ラッチを解放して、次の待機中のスレッドに付与します。など。

    7つの待機中のスレッドはすべてEXモードでラッチを待機していましたが、ラッチが付与されると何も実行されなかったため、7つのスレッドすべてが本質的に経過時間を浪費し、無駄になる時間はスレッドごとに少しずつ増加しました。それがあったFIFO待機キュー。

    ボトルネックを示す

    次に、拡張イベントを使用して、上記の正確なシナリオを示します。小さな自動拡張設定を使用して単一ファイルのデータベースを作成し、何百もの同時接続でデータをテーブルに挿入するだけです。

    次の拡張イベントセッションを使用して、何が起こっているかを確認できます。

      -- Drop the session if it exists. 
    IF EXISTS 
    (
      SELECT * FROM sys.server_event_sessions
        WHERE [name] = N'FGCB_ADDREMOVE'
    )
    BEGIN
      DROP EVENT SESSION [FGCB_ADDREMOVE] ON SERVER;
    END
    GO
     
    CREATE EVENT SESSION [FGCB_ADDREMOVE] ON SERVER
      ADD EVENT [sqlserver].[database_file_size_change]
      	(WHERE [file_type] = 0), -- data files only
      ADD EVENT [sqlserver].[latch_suspend_begin]
      	(WHERE [class] = 48 AND [mode] = 4),  -- EX mode
      ADD EVENT [sqlserver].[latch_suspend_end]
      	(WHERE [class] = 48 AND [mode] = 4) -- EX mode
      ADD TARGET [package0].[ring_buffer]
      WITH (TRACK_CAUSALITY = ON);
    GO
     
    -- Start the event session
    ALTER EVENT SESSION [FGCB_ADDREMOVE]
      ON SERVER STATE = START;
    GO

    セッションは、スレッドがラッチの待機キューに入るとき、キューを出るとき(つまり、ラッチが付与されるとき)、およびデータファイルの増大が発生するときを追跡しています。因果関係の追跡を使用すると、各スレッドによるアクションのタイムラインを確認できます。

    SQL Server Management Studioを使用して、拡張イベントセッションの[ライブデータの監視]オプションを選択し、すべての拡張イベントアクティビティを確認できます。同じことを行う場合は、[ライブデータ]ウィンドウで、上部の列名の1つを右クリックし、選択した列を次のように変更します。

    ワークロードを数分間実行して定常状態に到達させた後、上記のシナリオの完璧な例を確認しました。

    attach_activity_id.guidを使用する 異なるスレッドを識別するための値を見ると、7つのスレッドが61.5マイクロ秒以内にラッチの待機を開始していることがわかります。 8D57で始まるGUID値を持つスレッドは、EXモードでラッチを取得します(ラッチ_サスペンド_end イベント)、すぐにファイルを拡張します( database_file_size_change イベント)。次に、8D57スレッドはラッチを解放し、85ミリ秒待機した6F82スレッドにEXモードでそれを許可します。何の関係もないので、672Bスレッドにラッチを付与します。など、202ミリ秒待機した後、EDB8スレッドにラッチが付与されるまで続きます。

    合計で、理由もなく待機した6つのスレッドは、ほぼ1秒間待機しました。その時間の一部はシグナル待機時間であり、スレッドにラッチが付与されていても、プロセッサに到達してコードを実行する前に、スケジューラの実行可能キューの先頭に移動する必要があります。これは、ラッチの待機に費やされる時間の公正な尺度ではないと言うかもしれませんが、スレッドが最初に待機する必要がなかった場合、信号の待機時間は発生しなかったため、絶対にそうです。

    さらに、200ミリ秒の遅延はそれほど大きくないと思われるかもしれませんが、それはすべて、問題のワークロードのパフォーマンスサービスレベル契約に依存します。複数の大量のクライアントがあり、バッチの実行に200ミリ秒以上かかる場合、本番システムでは許可されません。

    概要

    サーバーでの待機を監視していて、LATCH_EXが上位の待機の1つであることに気付いた場合は、この投稿のコードを使用して、FGCB_ADD_REMOVEが原因の1つであるかどうかを確認できます。

    ワークロードがFGCB_ADD_REMOVEのボトルネックに達していないことを確認する最も簡単な方法は、SQLServer2016より前のデフォルトを使用して構成されたデータファイルの自動拡張設定がないことを確認することです。 sys.master_files内 ビューでは、1MBのデフォルトはデータファイル( type_desc 列をROWSに設定) is_percent_growth 列を0に設定し、成長列を128に設定します。

    自動成長をどのように設定するかについての推奨事項を示すことは、まったく別の議論ですが、以前のバージョンでデフォルトを変更しないことによる潜在的なパフォーマンスへの影響がわかりました。


    1. Linuxのカスタムキーストアで保護されたデータの使用

    2. MySQLベースのシステム(MySQL / MariaDBレプリケーション+ガレラ)用にSELinuxを構成する方法

    3. PostgreSQL/Oracleで2つの日付の差を計算する方法

    4. EntityFrameworkと複数のスキーマ