SQL Serverからデフォルトで取得できるイベント情報は何ですか?


60

特定の事柄が発生したかどうか、いつ発生したか、誰がアクションを実行したかを人々が知りたい質問をよく見ます。多くの場合、SQL Serverはこの情報を独自に追跡しません。例えば:

  • ストアドプロシージャを最後に実行したのは誰dbo.MyProcedureですか?
  • テーブルのsalary列を更新したのは誰dbo.Employeesですか?
  • 誰が最後にdbo.OrdersManagement Studioにテーブルを照会しましたか?

ただし、SQL Server デフォルトで一時的に追跡するイベントは他にもいくつかあり、次のような質問にネイティブに答えることができます。

  • AdventureWorksデータベースで自動拡張が最後に行われたのはいつで、どのくらいかかりましたか?
  • 誰がdbo.EmployeeAuditDataいつテーブルを削除しましたか?
  • 今日、メモリ関連のエラーがいくつ発生しましたか?

この情報を取得するにはどうすればよいですか?

回答:


65

SQL Serverがデフォルトで追跡する貴重な情報がかなりあります。SQL Server 2005以降、バックグラウンドで実行される「デフォルトトレース」があり、SQL Server 2008以降、と呼ばれる拡張イベントセッションが自動的に実行されていsystem_healthます。

また、SQL Serverエラーログ、SQL Serverエージェントログ、Windowsイベントログ、およびSQL Server監査管理データウェアハウスイベント通知DMLトリガーDDLトリガーSCOM / System Centerなどの追加のログから特定の情報を見つけることもできます。、独自のサーバー側トレースまたは拡張イベントセッション、またはサードパーティの監視ソリューション(私の雇用主であるSQL Sentryが作成したソリューションなど)。オプションで、いわゆる「ブラックボックストレース」を有効にして、トラブルシューティングを支援することもできます。

ただし、この投稿では、デフォルトのトレース、拡張イベントセッション、エラーログなど、一般的にどこでも有効になっているものに焦点を当てます。

デフォルトのトレース

デフォルトのトレースは、を使用しsp_configure無効にしない限り、通常ほとんどのシステムで実行されています。有効になっている限り、これは貴重な情報の豊富なソースになります。以下に、キャプチャされるトレースイベントを示します。

DECLARE @TraceID INT;

SELECT @TraceID = id FROM sys.traces WHERE is_default = 1;

SELECT t.EventID, e.name as Event_Description
  FROM sys.fn_trace_geteventinfo(@TraceID) t
  JOIN sys.trace_events e ON t.eventID = e.trace_event_id
  GROUP BY t.EventID, e.name;

に参加しsys.trace_columnsてどのイベントにどのデータが付随するかを確認することでより詳細になりますが、特定のイベントのトレースデータを実際にクエリするときに何があるかを見ることができるので、ここではスキップします。これらは私のシステムで利用可能なイベントです(これらが一致することを確認するためにクエリを実行する必要がありますが、これはまだSQL Server 2019 CTP 2.4を介した同じイベントのセットです):

EventID  Event_Description
-------  ----------------------------------------------
18       Audit Server Starts And Stops
20       Audit Login Failed
22       ErrorLog
46       Object:Created
47       Object:Deleted
55       Hash Warning
69       Sort Warnings
79       Missing Column Statistics
80       Missing Join Predicate
81       Server Memory Change
92       Data File Auto Grow
93       Log File Auto Grow
94       Data File Auto Shrink
95       Log File Auto Shrink
102      Audit Database Scope GDR Event
103      Audit Schema Object GDR Event
104      Audit Addlogin Event
105      Audit Login GDR Event
106      Audit Login Change Property Event
108      Audit Add Login to Server Role Event
109      Audit Add DB User Event
110      Audit Add Member to DB Role Event
111      Audit Add Role Event
115      Audit Backup/Restore Event
116      Audit DBCC Event
117      Audit Change Audit Event
152      Audit Change Database Owner
153      Audit Schema Object Take Ownership Event
155      FT:Crawl Started
156      FT:Crawl Stopped
164      Object:Altered
167      Database Mirroring State Change
175      Audit Server Alter Trace Event
218      Plan Guide Unsuccessful

デフォルトのトレースではロールオーバーファイルが使用されるため、使用可能なデータはこれまでにしか戻らないことに注意してください。使用可能なデータの日付範囲は、上記のイベントの数と取得頻度によって異なります。より長い履歴を保持したい場合は、トレースに関連付けられている現在非アクティブなファイルを定期的にアーカイブするジョブをセットアップできます。

質問では、私が見つけたいくつかの質問をしました。デフォルトトレースから特定の情報を取得するためのクエリの例を次に示します。

質問:AdventureWorksデータベースで最後に自動拡張が行われたのはいつでしたか?

このクエリは、ログファイルとデータファイルの両方について、AdventureWorksデータベース内のすべてのAutoGrowイベントをプルしますが、これらはまだデフォルトのトレースログファイルにあります。

DECLARE @path NVARCHAR(260);

SELECT 
   @path = REVERSE(SUBSTRING(REVERSE([path]), 
   CHARINDEX(CHAR(92), REVERSE([path])), 260)) + N'log.trc'
FROM    sys.traces
WHERE   is_default = 1;

SELECT 
   DatabaseName,
   [FileName],
   SPID,
   Duration,
   StartTime,
   EndTime,
   FileType = CASE EventClass WHEN 92 THEN 'Data' ELSE 'Log' END
FROM sys.fn_trace_gettable(@path, DEFAULT)
WHERE EventClass IN (92,93)
AND DatabaseName = N'AdventureWorks'
ORDER BY StartTime DESC;

質問:dbo.EmployeeAuditDataテーブルを削除したのはいつですか?

これによりDROP、という名前のオブジェクトのイベントが返されEmployeeAuditDataます。DROPテーブルのイベントのみを検出するようにしたい場合は、フィルターを追加できますObjectType = 8277完全なリストはここに記載されています)。サーチスペースを特定のデータベースに制限する場合は、フィルターを追加できますDatabaseName = N'db_name'

DECLARE @path NVARCHAR(260);

SELECT 
   @path = REVERSE(SUBSTRING(REVERSE([path]), 
   CHARINDEX(CHAR(92), REVERSE([path])), 260)) + N'log.trc'
FROM    sys.traces
WHERE   is_default = 1;

SELECT 
  LoginName,
  HostName,
  StartTime,
  ObjectName,
  TextData
FROM sys.fn_trace_gettable(@path, DEFAULT)
WHERE EventClass = 47    -- Object:Deleted
AND EventSubClass = 1
AND ObjectName = N'EmployeeAuditData'
ORDER BY StartTime DESC;

ここには複雑な問題があり、非常に端的なケースですが、とにかく言及するのが賢明だと思いました。複数のスキーマを使用し、複数のスキーマで同じオブジェクト名を使用している場合、これがどのスキーマであるかはわかりません(対応するスキーマがまだ存在しない場合)。UserAがSchemaB.Tablenameをドロップし、UserBがSchemaA.Tablenameをドロップしたという外部ケースがあります。デフォルトのトレースはオブジェクトのスキーマを追跡しません(またTextData、このイベントに対してキャプチャしません)。ObjectIDトレースに含まれているものは、直接一致する場合には役に立ちません(オブジェクトが削除されて存在しなくなったため)。この場合、出力にその列を含めることは、まだ存在する同じ名前のテーブルのコピーに対して相互参照するのに役立ちますが、システムがこれほど混乱している場合(またはそのようなコピーがすべて削除されている場合)それでも、誰がテーブルのコピーを削除したかを推測する信頼できる方法ではないかもしれません。

拡張イベント

SQL Server 2008のサポート:system_healthセッション(SQLCSSブログ)を、次はあなたがからカリングできるデータのリストであるsystem_healthSQL Server 2008および2008 R2でのセッション:

  • 重大度> = 20のエラーが発生したセッションのsql_textおよびsession_id
  • 17803、701などの「メモリ」タイプのエラーが発生したセッションのsql_textおよびsession_id(すべてのメモリエラーが重大度> = 20ではないため、これを追加しました)
  • 「降伏しない」問題の記録(エラーログでMsg 17883としてこれらを見たことがあります)
  • 検出されたデッドロック
  • ラッチ(またはその他の興味深いリソース)で15秒以上待機したセッションのコールスタック、sql_text、およびsession_id
  • ロックで30秒以上待機したセッションのcallstack、sql_text、およびsession_id
  • 「外部」待機または「プリエンプティブ待機」のために長時間待機したセッションのコールスタック、sql_text、およびsession_id。

使用system_healthイベントセッション(MSDN) 、リストは多少のSQL Server 2012に拡大(およびSQL Server 2014用に同じまま)されています。

  • 重大度が20以上のエラーが発生したセッションのsql_textおよびsession_id。
  • メモリ関連のエラーが発生したセッションのsql_textおよびsession_id。エラーには、17803、701、802、8645、8651、8657、8902が含まれます。
  • 降伏しないスケジューラーの問題の記録。(これらはSQL Serverエラーログにエラー17883として表示されます。)
  • 検出されたデッドロック。
  • ラッチ(またはその他の興味深いリソース)で15秒以上待機したセッションの呼び出しスタック、sql_text、およびsession_id。
  • ロックで30秒以上待機したセッションのcallstack、sql_text、およびsession_id。
  • プリエンプティブな待機を長時間待機したセッションのcallstack、sql_text、およびsession_id。期間は待機タイプによって異なります。プリエンプティブ待機は、SQL Serverが外部API呼び出しを待機している場所です。
  • CLR割り当ておよび仮想割り当てエラーのcallstackおよびsession_id。
  • メモリブローカ、スケジューラモニタ、メモリノードOOM、セキュリティ、および接続のring_bufferイベント。
  • システムコンポーネントは、sp_server_diagnosticsの結果です。
  • scheduler_monitor_system_health_ring_buffer_recordedによって収集されたインスタンスのヘルス。
  • CLR割り当てエラー。
  • connectivity_ring_buffer_recordedを使用した接続エラー。
  • security_error_ring_buffer_recordedを使用したセキュリティエラー。

SQL Server 2016では、さらに2つのイベントがキャプチャされます。

  • KILLコマンドを使用してプロセスが強制終了されたとき。
  • SQL Serverのシャットダウンが開始されたとき。

(ドキュメントはまだ更新されていませんが、これらの変更点やその他の変更点を発見した方法についてはブログに書きました。)

特定のバージョンに適用されるより暗号化された構成を取得するには、常に次のクエリを直接実行できますが、名前を解釈し、上記のより自然な言語リストに一致するように述語を解析する必要があります。

SELECT e.package, e.event_id, e.name, e.predicate
  FROM sys.server_event_session_events AS e
  INNER JOIN sys.server_event_sessions AS s
  ON e.event_session_id = s.event_session_id
 WHERE s.name = N'system_health'
 ORDER BY e.package, e.name;

可用性グループを使用している場合、実行中の新しいセッションが2つあります:AlwaysOn_failoverAlwaysOn_health。次のクエリを使用して、収集したデータを確認できます。

SELECT s.name, e.package, e.event_id, e.name, e.predicate
  FROM sys.server_event_session_events AS e
  INNER JOIN sys.server_event_sessions AS s
  ON e.event_session_id = s.event_session_id
 WHERE s.name LIKE N'AlwaysOn[_]%'
 ORDER BY s.name, e.package, e.name;

これらのイベントセッションは、リングバッファターゲットを使用してデータを格納するため、バッファプールやプランキャッシュなど、古いイベントは段階的に廃止されるため、必要な日付範囲からイベントをプルできるとは限りません。

私はこの架空の質問を投げかけました。

今日、メモリ関連のエラーがいくつ発生しましたか?

以下は、system_healthセッションからこの情報を引き出すことができるサンプルのクエリです(おそらくあまり効率的ではありません)。

;WITH src(x) AS
(
  SELECT y.query('.')
  FROM
  (
    SELECT x = CONVERT(XML, t.target_data)
      FROM sys.dm_xe_sessions AS s
      INNER JOIN sys.dm_xe_session_targets AS t
      ON s.[address] = t.event_session_address
      WHERE s.name = N'system_health'
  ) AS x
  CROSS APPLY x.x.nodes('/RingBufferTarget/event') AS y(y)
)
SELECT 
  x, ts = CONVERT(DATETIME, NULL), err = CONVERT(INT, NULL)
INTO #blat FROM src;

DELETE #blat WHERE x.value('(/event/@name)[1]', 'varchar(255)') <> 'error_reported';

UPDATE #blat SET ts = x.value('(/event/@timestamp)[1]', 'datetime');

UPDATE #blat SET err = x.value('(/event/data/value)[1]', 'int');

SELECT err, number_of_events = COUNT(*)
  FROM #blat
  WHERE err IN (17803, 701, 802, 8645, 8651, 8657, 8902)
  AND ts >= CONVERT(DATE, CURRENT_TIMESTAMP)
  GROUP BY err;

DROP TABLE #blat;

(この例はsystem_healthセッションに関するAmit Banerjeeの紹介ブログ投稿から大まかに借りています。)

拡張イベントの詳細(特定のデータを照会できる多くの例を含む)については、Jonathan Kehayiasによる次の31部のブログシリーズを参照してください。

https://www.sqlskills.com/blogs/jonathan/an-xevent-a-day-31-days-of-extended-events/

エラーログ

SQL Serverは、デフォルトで現在のプラス6個の最新のエラーログファイルを保持します(ただし、これは変更できます)。スタートアップ情報(使用中のコアの数、メモリ内のロックページが設定されているかどうか、認証モードなど)だけでなく、ドキュメント化するのに十分なエラー(および他の場所でキャプチャされていない)その他のシナリオなど、多くの情報がそこに保存されます。最近の例の1つは、データベースがオフラインになったときに探している人です。これを判断するには、最新の7つのエラーログでテキストをスキャンしますSetting database option OFFLINE

EXEC sys.sp_readerrorlog 0,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 1,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 2,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 3,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 4,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 5,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 6,1,'Setting database option OFFLINE';

この最近の回答で他のいくつかの詳細をカバーしました。またtoadworld公式文書にも良い背景情報があります

エラーログがデフォルトで追跡する「エラー」の1つのグループ-そして重要な情報を尾からより速く落とすことができる-成功したすべてのバックアップメッセージです。トレースフラグ3226を有効にすることにより、エラーログがノイズでいっぱいになるのを防ぐことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.