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

デフォルトのトレースの削除–パート1

    [パート1|パート2|パート3]

    グラント・フリッチーの最近の暴言の精神と、私たちが会う前に考えていたエリン・ステラートの努力の中で、私は時流に乗ってトランペットを演奏し、拡張イベントを支持してトレースを捨てるというアイデアを推進したいと思います。誰かがトレースと言ったとき 、ほとんどの人はすぐにプロファイラーだと思います 。 Profilerはそれ自体が特別な悪夢ですが、今日はSQLServerのデフォルトのトレースについて話したいと思いました。

    私たちの環境では、200以上の本番サーバーすべてで有効になっており、調査することのない大量のガベージを収集します。実際、非常に多くのゴミが発生するため、トラブルシューティングに役立つ可能性のある重要なイベントが、機会を得る前にトレースファイルからロールアウトされます。それで、私はそれをオフにする可能性を検討し始めました。理由は次のとおりです。

    • 無料ではありません (トレースアクティビティ自体のオブザーバーオーバーヘッド、トレースファイルへの書き込みに関連するI / O、およびそれらが消費するスペース);
    • ほとんどのサーバーでは、見たことがない;他の人には、めったにありません。と、
    • オンに戻すのは簡単です 特定の個別のトラブルシューティング用。

    他のいくつかのことがデフォルトのトレースの値に影響します。構成することはできません。収集するイベントを変更したり、フィルターを追加したり、保持するファイルの数(5)、取得できるファイルのサイズ(各20 MB)を制御したりすることはできません。 、またはそれらが保存されている場所(SERVERPROPERTY('ErrorLogFileName') )。したがって、私たちは完全にワークロードに翻弄されます。どのサーバーでも、データがどこまで遡るかを予測することはできません(TextDataが大きいイベント) たとえば、値はより多くのスペースを占有し、古いイベントをより迅速にプッシュする可能性があります)。 1週間前に戻ることもあれば、数分前に戻ることもあります。

    現在の状態の分析

    環境全体でデフォルトのトレースを埋めているノイズの種類を理解するために、224の実稼働インスタンスに対して次のコードを実行しました。これはおそらく必要以上に複雑であり、私が使用した最後のクエリほど複雑ではありませんが、現在キャプチャされている高レベルのイベントタイプの内訳を分析するための適切な出発点です:

    >
    ;WITH filesrc ([path]) AS
    (
      SELECT REVERSE(SUBSTRING(p, CHARINDEX(N'\', p), 260)) + N'log.trc'
      FROM (SELECT REVERSE([path]) FROM sys.traces WHERE is_default = 1) s(p)
    ),
    tracedata AS 
    (
      SELECT Context = CASE 
        WHEN DDL = 1 THEN 
          CASE WHEN LEFT(ObjectName,8) = N'_WA_SYS_' 
                    THEN 'AutoStat: ' + DBType
               WHEN LEFT(ObjectName,2) IN (N'PK', N'UQ', N'IX') AND ObjectName LIKE N'%[_#]%' 
                    THEN UPPER(LEFT(ObjectName,2)) + ': tempdb'
               WHEN ObjectType = 17747 AND ObjectName LIKE N'TELEMETRY%' 
                    THEN 'Telemetry' 
                    ELSE 'Other DDL in ' + DBType END
        WHEN EventClass = 116 THEN 
          CASE WHEN TextData LIKE N'%checkdb%' THEN 'DBCC CHECKDB'
               -- several more of these ...
               ELSE UPPER(CONVERT(nchar(32), TextData)) END
        ELSE DBType END,
        EventName = CASE WHEN DDL = 1 THEN 'DDL' ELSE EventName END, 
        EventSubClass,
        EventClass, 
        StartTime
      FROM
      (
        SELECT DDL = CASE WHEN t.EventClass IN (46,47,164) THEN 1 ELSE 0 END, 
          TextData = LOWER(CONVERT(nvarchar(512), t.TextData)), 
          EventName = e.[name],
          t.EventClass, 
          t.EventSubClass, 
          ObjectName = UPPER(t.ObjectName), 
          t.ObjectType, 
          t.StartTime,
          DBType = CASE WHEN t.DatabaseID = 2 OR t.ObjectName LIKE N'#%' THEN 'tempdb'
                        WHEN t.DatabaseID IN (1,3,4)  THEN 'System database'
                        WHEN t.DatabaseID IS NOT NULL THEN 'User database' ELSE '?' END
        FROM filesrc CROSS APPLY sys.fn_trace_gettable(filesrc.[path], DEFAULT) AS t
        LEFT OUTER JOIN sys.trace_events AS e ON t.EventClass = e.trace_event_id
      ) AS src WHERE (EventSubClass IS NULL) 
               OR (EventSubClass = CASE WHEN DDL = 1 THEN 1 ELSE EventSubClass END) -- ddl_phase
    )
    SELECT [Instance] = @@SERVERNAME, 
           EventName,   
           Context, 
           EventCount = COUNT(*), 
           FirstSeen  = MIN(StartTime), 
           LastSeen   = MAX(StartTime) 
    INTO #t FROM tracedata 
    GROUP BY GROUPING SETS ((), (EventName, Context));
    (EventSubClass述語は、DDLイベントの二重カウントを防ぐためにあります。
    EventClass値のマップについては、Stack Exchangeのこの回答にリストしました。)

    そして、結果はきれいではありません(ランダムサーバーからの典型的な結果)。以下はそのクエリの正確な出力を表すものではありませんが、結果をより消化しやすい形式に集約して、有用なデータの量とノイズの量を確認するために時間を費やしました(クリックして拡大):

    >

    ほとんどすべてのノイズ(99.94%)。デフォルトのトレースから必要だった唯一の便利なものは、ファイルの拡大イベントと縮小イベントでした。これは、他の場所で何らかの方法でキャプチャしなかった唯一のイベントでした。しかし、それでも、データがすぐにロールアウトするため、常に信頼できるとは限りません。

    データをスライスする別の方法:インスタンスごとの最も古いイベント。一部のインスタンスにはノイズが多すぎて、デフォルトのトレースデータを数分以上保持できませんでした。サーバー名をぼかしましたが、これは実際のデータです(これらは、履歴が最も短い20台のサーバーです。クリックして拡大します):

    トレースが収集されていたとしてものみ 関連情報、そして何か面白いことが起こった場合、サーバーによっては、それをキャッチするために迅速に行動する必要があります。発生した場合:

    • 20分前 、その後、15インスタンスですでに実行されています 。
    • 昨日の今回105インスタンスで実行されます 。
    • 2日前115インスタンスで実行されます 。
    • 1週間以上前139インスタンスで実行されます 。

    もう一方の端にも少数のサーバーがありましたが、このコンテキストでは興味がありません。これらのサーバーは、興味深いことが何も起こらないという理由だけでそのようになっています(たとえば、サーバーがビジーでないか、重要なワークロードの一部ではありません)。

    プラス面…

    デフォルトのトレースを調査したところ、いくつかのサーバーでいくつかの設定ミスが明らかになりました:

    • いくつかのサーバーではまだテレメトリが有効になっています 。私はすべて、特定の環境でMicrosoftを支援することに尽力していますが、ビジネスクリティカルなシステムのオーバーヘッドコストはありません。
    • バックグラウンド同期タスクの中には、メンバーを盲目的に役割に追加するものがありました。 、何度も何度も、彼らがすでにそれらの役割を果たしているかどうかを確認せずに。これ自体は有害ではありません。特に、これらのイベントはデフォルトのトレースをいっぱいにしないためですが、監査もノイズでいっぱいになる可能性があり、同じパターンで他のブラインド再適用操作が発生している可能性があります。
    • 誰かが自動縮小を有効にした どこかで(良い悲しみ!)、これは私が追跡して二度と起こらないようにしたかったものでした(新しいXEはこれらのイベントもキャプチャします)。

    これにより、これらの問題を修正したり、既存の自動化に条件を追加したりするためのフォローアップタスクが発生しました。そのため、将来のデフォルトのトレースレビューで、ロールアウトされる前に幸運にも発生することに依存することなく、再発を防ぐことができます。

    …しかし問題は残っています

    それ以外の場合、すべては、私たちが行動できない可能性のある情報か、上の図で説明されているように、すでに他の場所でキャプチャしたイベントのいずれかです。繰り返しになりますが、他の方法でまだキャプチャしていないデフォルトのトレースから関心のあるデータは、ファイルの拡大と縮小に関連するイベントだけです(デフォルトのトレースは自動多様性のみをキャプチャします)。

    しかし、より大きな問題は、実際にはノイズの量ではありません。 WHERE句はまさにこの目的のために考案されたので、大量のガベージを含む大きな大量のトレースファイルを処理できます。本当の問題は、重要なイベントがあまりにも早く消えていたということです。

    答え

    少なくとも私たちのシナリオでは、答えは単純でした。信頼できない場合は実行する価値がないため、デフォルトのトレースを無効にします。

    しかし、上記のノイズの量を考えると、何を置き換える必要がありますか?何か?

    すべてをキャプチャする拡張イベントセッションが必要になる場合があります キャプチャされたデフォルトのトレース。もしそうなら、ジョナサンケハイアスはあなたをカバーしています。これにより同じ情報が得られますが、データが保存される保持などを制御でき、快適になるにつれて、ノイズの多いイベントや役に立たないイベントの一部を時間の経過とともに徐々に削除できるようになります。

    >

    私の計画はもう少し積極的で、すぐに環境内のすべてのサーバーで(CMSを介して)次のことを実行する「単純な」プロセスになりました。

    1. ファイル変更イベントのみをキャプチャする拡張イベントセッションを開発する(手動と自動の両方)
    2. デフォルトのトレースを無効にする
    3. ビューを作成して、チームがターゲットデータを簡単に利用できるようにします

    デフォルトのトレースをやみくもに無効にすることをお勧めしているわけではないことに注意してください 、私が私たちの環境でそうすることを選んだ理由を説明するだけです。このシリーズの今後の投稿では、新しい拡張イベントセッション、基になるデータを公開するビュー、これらの変更をすべてのサーバーにデプロイするために使用したコード、および留意すべき潜在的な副作用について説明します。

    >

    [パート1|パート2|パート3]


    1. SQL Serverの別のデータベースからOBJECT_NAME()を取得する方法

    2. MySQLのパフォーマンス–遅いクエリとinnodb_buffer_pool_size

    3. uuidを数値として保存する方法は?

    4. HerokuでのPumaクラスター構成