[ Teil 1 | Teil 2 | Teil 3 ]
In Teil 1 dieser Serie habe ich erklärt, wie ich zu dem Schluss kam, dass wir den Standard-Trace deaktivieren sollten. In Teil 2 habe ich die Extended Events-Sitzung gezeigt, die ich bereitgestellt habe, um alle Ereignisse zur Änderung der Dateigröße zu erfassen. In diesem Beitrag möchte ich die Ansichten zeigen, die ich erstellt habe, um den Benutzern die Nutzung der Ereignisdaten zu erleichtern, und auch einige Vorbehalte erläutern.
Verdauliche Ansichten
Zuerst habe ich eine Ansicht erstellt, die die wichtigen Teile der Sitzungsdaten für erweiterte Ereignisse offenlegt, und sie in die Dienstprogrammdatenbank eingefügt, die auf jeder Instanz vorhanden ist:
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;
Wenn nun jemand die jüngsten Dateigrößenänderungsereignisse auf einem beliebigen Server überprüfen möchte, führt er Folgendes aus:
SELECT <cols> FROM UtilityDatabase.dbo.vwFileSizeChanges ORDER BY StartTimeUTC DESC;
Wenn Sie die Standardablaufverfolgung deaktivieren, werden die Ablaufverfolgungsdateien nicht gelöscht, sodass alle Ereignisse vor dieser Änderung weiterhin überprüft werden können. Ich kann mir die Tatsache ausleihen, dass die Standardablaufverfolgung auf denselben Pfad wie SERVERPROPERTY(N'ErrorLogFileName')
hartcodiert ist , und erstellen Sie eine zweite Ansicht, die die obigen Daten mit weiteren Daten aus dem Standard-Trace verbindet:
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;
Diese Ansicht passt die Ablaufverfolgungsdaten (auf allen unseren Servern in Eastern Time erfasst) an UTC an und behandelt gegebenenfalls auch die Sommerzeit. Wenn die Daten außerhalb des Bereichs des CTE namens dst
liegen , wird es stattdessen in Eastern Time ausgedrückt (und Sie können dies leicht beheben, indem Sie weitere DST-Bereiche hinzufügen). Es gibt eine zusätzliche Spalte namens src
damit Sie die alten Trace-Daten abfragen können mit:
SELECT <cols> FROM UtilityDatabase.dbo.vwFileSizeChanges_IncludingTrace WHERE src = 'trace' ORDER BY StartTimeUTC DESC;
Warnhinweise
Es gibt kein kostenloses Mittagessen! Obwohl ich zuversichtlich bin, dass das Entfernen des Standard-Trace keine oder viel wahrscheinlicher positive Auswirkungen auf unsere Workloads haben wird, gibt es einige Dinge, die Sie für Ihre Umgebung beachten sollten, wenn Sie sich dafür entscheiden, meinem Weg zu folgen:
- Datenbanken sind nicht dauerhaft
In meiner Sitzungsdefinition für erweiterte Ereignisse habe ich mich dafür entschieden,
collect_database_name
nicht zu implementieren , und in der obigen Ansicht können Sie sehen, dass ich dies zur Laufzeit mitDB_NAME(database_id)
auflöse . Hier besteht das Risiko, dass jemand eine Datenbank erstellt, eine Reihe von Aktivitäten durchführt, die zu Dateiabwanderungen und Festplatten-Thrashing führen, und dann die Datenbank löschen könnte. Diedatabase_id
exponiert im XML ist in diesem Fall nicht mehr aussagekräftig undDB_NAME()
gibtNULL
zurück .Ich habe mich für dieses Ergebnis entschieden, anstatt mich ausschließlich auf den Datenbanknamen zu verlassen, da die obige Ereigniskette weit weniger wahrscheinlich ist als eine Datenbankumbenennung (wobei eine
database_id
bleibt gleich). In diesem Fall suchen Sie möglicherweise nach Ereignissen, die mit einer Datenbank passiert sind, suchen aber mit dem falschen (aktuellen) Namen, je nachdem, wann die Ereignisse aufgetreten sind.Wenn Sie das eine oder das andere verwenden möchten, können Sie stattdessen die folgende Sitzungsdefinition verwenden:
... ADD EVENT sqlserver.database_file_size_change ( SET collect_database_name = (1) ACTION ( sqlserver.sql_text, ...
Dies kann auch nicht kostenlos sein, oder es würde standardmäßig passieren, aber ich gebe zu, dass ich die Auswirkungen des Hinzufügens zur Sammlung nie getestet habe.
- SSMS-Berichte sind etwas weniger zuverlässig
Ein Nebeneffekt der Deaktivierung des Standard-Trace ist die Störung einiger der „Standardberichte“ von Management Studio. Ich habe unsere Teams befragt, bevor ich dies getan habe, und Sie sollten dasselbe tun, um sicherzustellen, dass sich Ihre Benutzer nicht auf diese verlassen. Sie sollten sie auch daran erinnern, dass auf die Berichte derzeit ohnehin kein Verlass ist, aus dem gleichen Grund, aus dem ich mich nicht direkt auf die Standardablaufverfolgung verlassen kann – sie können nur Daten abrufen, die sich noch in der Ablaufverfolgung befinden. Ein leerer Bericht bedeutet nicht unbedingt, dass keine Ereignisse stattgefunden haben; es könnte lediglich bedeuten, dass die Informationen nicht mehr verfügbar sind. Wenn ein Team diese Informationen wirklich nutzen möchte, könnte ich sicherstellen, dass sie zuverlässig sind, indem ich ihnen benutzerdefinierte Berichte zusende, die eine vertrauenswürdigere Quelle verwenden.
Die folgenden Berichte sind diejenigen, von denen ich sehen konnte, dass sie zumindest einige ihrer Informationen aus dem Standard-Trace ableiten und warum wir die Berichte nicht brauchen, selbst wenn man ihnen vertrauen könnte:
Verlauf der Schemaänderungen Wir haben bereits eine Quellcodeverwaltung, einen strengen Überprüfungs-/Bereitstellungsprozess und DDL-Auslöser, die Informationen über Schemaänderungen erfassen. Verlauf der Konfigurationsänderungen
und
SpeicherverbrauchUnser Überwachungstool informiert uns über Konfigurationsänderungen auf Instanzebene, sodass dieser Bericht in SSMS überflüssig ist. Anmeldefehler Diese befinden sich im Fehlerprotokoll (und in der Ereignisanzeige), da wir standardmäßig die Überwachung „Nur fehlgeschlagene Anmeldungen“ für alle SQL Server-Instanzen aktivieren. Einige Server haben auch aus Compliance-Gründen eine zusätzliche formelle Prüfung. Festplattennutzung Hier werden neben anderen Informationen die Autogrowth- und Autoshrink-Ereignisse aus dem Standard-Trace aufgelistet, die wir jetzt mit Extended Events erfassen. Ereignisse sichern und wiederherstellen Diese Informationen sind jederzeit in msdb.dbo.backupset verfügbar, wenn wir sie jemals benötigen, aber sie fließen auch in unsere Automatisierung rund um Sicherung und Wiederherstellung ein (wir sehen uns niemals den Standard-Trace für diese Informationen an).
Datenbankkonsistenzverlauf Wie bei Sicherungen haben wir die Automatisierung um DBCC CHECKDB herum aufgebaut; Wenn jemand außerhalb davon gegangen ist und etwas manuell ausgeführt hat, wird es immer noch im Fehlerprotokoll angezeigt. Und wir haben viel mehr Kontrolle darüber, wie lange wir Fehlerprotokolle aufbewahren und wie oft wir sie wiederverwenden. Wir recyceln jede Nacht, damit es einfacher ist, ein Ereignis zu finden, von dem wir vermuten, dass es an einem bestimmten Tag in der Vergangenheit stattgefunden hat.
Schlussfolgerung
Das war ein lustiges, aber kompliziertes Projekt, und ich bin mit dem bisherigen Ergebnis zufrieden. Danke, dass du mitgefahren bist!
[ Teil 1 | Teil 2 | Teil 3 ]