Database
 sql >> Datenbank >  >> RDS >> Database

Entfernen des Standard-Trace – Teil 3

[ 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:

  1. 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 mit DB_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. Die database_id exponiert im XML ist in diesem Fall nicht mehr aussagekräftig und DB_NAME() gibt NULL 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.

  2. 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
    Speicherverbrauch
    Unser Ü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 ]