[パート1|パート2|パート3]
このシリーズのパート1では、デフォルトのトレースを無効にする必要があるという結論に到達した方法を説明しました。パート2では、すべてのファイルサイズ変更イベントをキャプチャするために展開した拡張イベントセッションを示しました。この投稿では、イベントデータをより簡単に利用できるようにするために作成したビューを示し、いくつかの注意点についても説明します。
消化可能なビュー
最初に、拡張イベントセッションデータから重要なビットを公開するビューを作成し、それをすべてのインスタンスに存在するユーティリティデータベースに配置しました。
CREATE VIEW dbo.vwFileSizeChanges
AS
WITH FileInfo(XEPath) AS
(
SELECT LEFT(BasePath,COALESCE(NULLIF(CHARINDEX(SessName,BasePath)-1,-1),0)) + SessName + N'*.xel'
FROM
(
SELECT xmlsrc.data.value(N'(@name)[1]', N'nvarchar(max)'), SessName
FROM
(
SELECT CONVERT(xml,target_data), s.[name]
FROM sys.dm_xe_session_targets AS t
INNER JOIN sys.dm_xe_sessions AS s
ON s.[address] = t.event_session_address
WHERE s.[name] = N'FileSizeChanges'
) AS xefile (TargetData, SessName)
CROSS APPLY TargetData.nodes(N'//EventFileTarget/File') AS xmlsrc(data)
) AS InnerData(BasePath, SessName)
),
SessionData([EventData]) AS
(
SELECT CONVERT(xml, TargetData.event_data) FROM FileInfo CROSS APPLY
sys.fn_xe_file_target_read_file(FileInfo.XEPath, NULL, NULL, NULL) AS TargetData
),
src AS
(
SELECT
EndTimeUTC = x.d.value(N'(@timestamp)[1]', N'datetime2'),
DatabaseID = x.d.value(N'(data [@name="database_id"]/value)[1]', N'int'),
[FileName] = x.d.value(N'(data [@name="file_name"]/value)[1]', N'sysname'),
Duration = x.d.value(N'(data [@name="duration"]/value)[1]', N'int'),
FileType = x.d.value(N'(data [@name="file_type"]/text)[1]', N'varchar(4)'),
Culprit = x.d.value(N'(action[@name="sql_text"]/value)[1]', N'nvarchar(max)'),
IsAutomatic = x.d.value(N'(data [@name="is_automatic"]/value)[1]', N'varchar(5)'),
ChangeKB = x.d.value(N'(data [@name="size_change_kb"]/value)[1]', N'bigint'),
Principal = x.d.value(N'(action[@name="server_principal_name"]/value)[1]', N'sysname'),
username = x.d.value(N'(action[@name="username"]/value)[1]', N'sysname'),
AppName = x.d.value(N'(action[@name="client_app_name"]/value)[1]', N'sysname'),
HostName = x.d.value(N'(action[@name="client_hostname"]/value)[1]', N'sysname')
--, [EventData] -- raw XML to troubleshoot specific events
FROM SessionData CROSS APPLY EventData.nodes('/event') AS x(d)
)
SELECT
DatabaseName = DB_NAME(DatabaseID),
[FileName],
DurationSeconds = CONVERT(decimal(18,3),Duration/1000000.0),
StartTimeUTC = CONVERT(datetime2(3), DATEADD(MICROSECOND, -Duration, EndTimeUTC)),
EndTimeUTC = CONVERT(datetime2(3), EndTimeUTC),
FileType,
Culprit = CASE WHEN Culprit IS NULL AND AppName LIKE N'Repl%'
THEN AppName ELSE Culprit END,
IsAutomatic,
ChangeMB = CONVERT(decimal(18,3), ChangeKB / 1024.0),
Principal = COALESCE([Principal], COALESCE(NULLIF(username,N''),N'?')),
HostName,
App = CASE WHEN AppName LIKE N'%Management Studio%Query%'
THEN N'SSMS - Query Window'
WHEN AppName LIKE N'%Management Studio%'
THEN N'SSMS - GUI!'
ELSE AppName END--, [EventData] -- raw XML to troubleshoot specific events
FROM src; これで、誰かが任意のサーバーで最近のファイルサイズ変更イベントを確認したい場合、次のように実行されます。
SELECT <cols> FROM UtilityDatabase.dbo.vwFileSizeChanges ORDER BY StartTimeUTC DESC;
デフォルトのトレースを無効にしても、トレースファイルは削除されないため、その変更前のイベントは引き続き確認できます。デフォルトのトレースがSERVERPROPERTY(N'ErrorLogFileName')と同じパスにハードコードされているという事実から借りることができます。 、そして、上記のデータをデフォルトのトレースからのより多くのデータと結合する2番目のビューを作成します。
CREATE VIEW dbo.vwFileSizeChanges_IncludingTrace
AS
WITH dst AS
(
SELECT s,e,d
FROM (VALUES ('20190310','20191103',240),('20191103','20200308',300),
('20200308','20201101',240),('20201101','20210314',300),
('20210314','20211107',240)) AS dst(s,e,d)
-- arbitrary date range to support DST conversions going a year+ each way
-- will add 2022, 2023, etc. later (if DST is still a thing then)
),vars(TracePath) AS
(
SELECT REVERSE(SUBSTRING(p, CHARINDEX(N'\', p), 260)) + N'log.trc' FROM
(SELECT REVERSE((CONVERT(nvarchar(max), SERVERPROPERTY(N'ErrorLogFileName'))))) AS s(p)
),
trc AS
(
SELECT
t.DatabaseName,
t.[FileName],
DurationSeconds = CONVERT(decimal(18,3), t.Duration/1000000.0),
StartTimeUTC = CONVERT(datetime2(3), DATEADD(MINUTE, COALESCE(st1.d,0), t.StartTime)),
EndTimeUTC = CONVERT(datetime2(3), DATEADD(MINUTE, COALESCE(st2.d,0), t.EndTime)),
FileType = CASE WHEN t.EventClass IN (92, 94) THEN 'Data'
WHEN t.EventClass IN (93, 95) THEN 'Log' END,
Culprit = CASE WHEN t.TextData IS NULL AND t. ApplicationName LIKE N'Repl%'
THEN t.ApplicationName ELSE t.TextData END,
IsAutomatic = 'true',
ChangeMB = CONVERT(bigint, t.IntegerData)*8/1024,
Principal = t.LoginName,
t.HostName,
App = CASE WHEN t.ApplicationName LIKE N'%Management Studio%Query%'
THEN N'SSMS - Query Window'
WHEN t.ApplicationName LIKE N'%Management Studio%'
THEN N'SSMS - GUI!'
ELSE t.ApplicationName END --, [EventData] = CONVERT(xml, NULL)
FROM vars CROSS APPLY sys.fn_trace_gettable(vars.TracePath, DEFAULT) AS t
LEFT OUTER JOIN dst AS st1 ON t.StartTime >= DATEADD(HOUR,2,st1.s)
AND t.StartTime < DATEADD(HOUR,2,st1.e)
LEFT OUTER JOIN dst AS st2 ON t.EndTime >= DATEADD(HOUR,2,st2.s)
AND t.EndTime < DATEADD(HOUR,2,st2.e)
WHERE t.EventClass IN (92,93)
)
SELECT src='trace', * FROM trc
UNION ALL
SELECT src='xe', * FROM dbo.vwFileSizeChanges;
このビューは、トレースデータ(すべてのサーバーで東部標準時にキャプチャされたもの)をUTCに調整し、必要に応じてDSTも処理します。データがdstと呼ばれるCTEの範囲外にある場合 、代わりに東部時間で表されます(DST範囲を追加することでこれを簡単に修正できます)。 srcという追加の列があります したがって、次を使用して古いトレースデータをクエリできます:
SELECT <cols> FROM UtilityDatabase.dbo.vwFileSizeChanges_IncludingTrace WHERE src = 'trace' ORDER BY StartTimeUTC DESC;
警告
フリーランチのようなものはありません!デフォルトのトレースを削除しても、ワークロードに影響がないか、おそらくプラスの影響があると確信していますが、私の道をたどることを選択した場合は、環境に留意すべき点がいくつかあります。
- データベースは永続的ではありません
拡張イベントセッション定義で、
collect_database_nameを実装しないことを選択しました 、上記のビューでは、実行時にDB_NAME(database_id)を使用してこれを解決していることがわかります。 。ここには、誰かがデータベースを作成し、ファイルチャーンとディスクスラッシングを作成する一連のアクティビティを実行してから、データベースを削除する可能性があるというリスクがあります。database_idこの場合、XMLで公開されていることは意味がなくなり、DB_NAME()NULLを返します 。上記の一連のイベントはデータベースの名前変更(
database_idの場合)よりもはるかに少ないため、データベース名のみに依存するよりもこの結果を選択しました。 同じままになります)。その場合、データベースで発生したイベントを検索している可能性がありますが、イベントが発生した時期によっては、間違った(現在の)名前を使用して検索しています。どちらか一方を使用できるようにする場合は、代わりに次のセッション定義を使用できます。
... ADD EVENT sqlserver.database_file_size_change ( SET collect_database_name = (1) ACTION ( sqlserver.sql_text, ...これも無料にすることはできません。デフォルトで発生しますが、コレクションに追加した場合の影響をテストしたことはありません。
- SSMSレポートの信頼性はわずかに低下します
デフォルトのトレースを無効にすると、ManagementStudioの「標準レポート」の一部が中断されます。これを行う前にチームをポーリングしました。ユーザーがこれらのいずれにも依存しないようにするために、同じことを行う必要があります。また、デフォルトのトレースに直接依存できないのと同じ理由で、レポートは現在信頼できないことを彼らに思い出させてください。彼らはまだトレースに残っているデータしかプルできません。空のレポートは、必ずしもイベントが発生しなかったことを意味するわけではありません。情報が利用できなくなったことを意味している可能性があります。これが本当にチームがこの情報を利用したい場所である場合は、より信頼できるソースを使用するカスタムレポートを出荷することで、信頼できることを確認できます。
次のレポートは、デフォルトのトレースから少なくとも一部の情報を導き出していることがわかり、信頼できる場合でもレポートが不要な理由を示しています。
スキーマ変更履歴 すでにソース管理、厳密なレビュー/デプロイプロセス、スキーマの変更に関する情報をキャプチャするDDLトリガーが用意されています。 構成変更履歴
および
メモリ消費監視ツールはインスタンスレベルの構成変更について通知するため、SSMSのこのレポートは冗長です。 ログインの失敗 これらはエラーログ(およびイベントビューア)にあります。これは、標準として、すべてのSQLServerインスタンスに対して「失敗したログインのみ」の監査を有効にしているためです。一部のサーバーには、コンプライアンス上の理由から、追加の正式な監査もあります。 ディスク使用量 他の情報の中でも、これはデフォルトのトレースからの自動成長イベントと自動縮小イベントを一覧表示します。これは現在、拡張イベントを使用してキャプチャしています。 バックアップおよび復元イベント この情報は、必要に応じてmsdb.dbo.backupsetですぐに利用できますが、バックアップと復元に関する自動化にも組み込まれています(この情報のデフォルトのトレースを確認することはありません)。
データベースの整合性履歴 バックアップと同様に、DBCCCHECKDBを中心に自動化が構築されています。誰かがこれの外に出て手動で何かを実行した場合でも、それはエラーログに表示されます。また、エラーログを保持する期間と、それらをリサイクルする頻度をより詳細に制御できます。過去の特定の日に発生したと思われるイベントを見つけやすくするために、毎晩リサイクルしています。
結論
これは楽しいが複雑なプロジェクトであり、これまでの結果に満足しています。一緒に乗ってくれてありがとう!
[パート1|パート2|パート3]