Abfrage, die Sicherungsinformationen anzeigt (erfolgreich und fehlgeschlagen) SQL Server

8

Ich habe zwei Jobs, die zwei verschiedene Datenbanken sichern.
Job 1 sichert DB1
Job 2 sichert DB2

DB1 kann nicht gesichert werden, da auf Laufwerk 1 nur wenig Speicherplatz vorhanden ist und Job 1 fehlschlägt. Um dieses Problem zu beheben, musste ich nur Speicherplatz hinzufügen. Kein Problem. Mir wurde heute davon erzählt, als das Problem seit einem Monat auftritt. Ja, ich weiß, dass es verrückt ist, aber es ist Entwickler


Ich möchte einen vollständigen Sicherungsverlauf für DB1 erhalten. Ich weiß, dass ich erfolgreiche Sicherungsinformationen aus der Tabelle msdb.dbo.backupset abrufen kann, möchte aber wissen, ob es eine Abfrage gibt, die fehlgeschlagene Sicherungen für eine Datenbank anzeigt.

In meiner folgenden Abfrage wird der Sicherungsverlauf für eine bestimmte Datenbank vom 31.12.13-1 / 27/14 angezeigt. Zu den Informationen gehören Server, Datenbankname, Start- und Endzeit der Sicherung, Gesamtzeit für die Sicherung der Datenbank, Datenbankgröße und Name des Sicherungssatzes.

SELECT  
   distinct CONVERT(CHAR(100), SERVERPROPERTY('Servername')) AS Server, 
   msdb.dbo.backupset.database_name,  
   msdb.dbo.backupset.backup_start_date,  
   msdb.dbo.backupset.backup_finish_date, 
 CAST((DATEDIFF(second,  msdb.dbo.backupset.backup_start_date,msdb.dbo.backupset.backup_finish_date)) AS varchar)+ ' secs  ' AS [Total Time] ,

   Cast(msdb.dbo.backupset.backup_size/1024/1024 AS numeric(10,2)) AS 'Backup Size(MB)',   
   msdb.dbo.backupset.name AS backupset_name
FROM   msdb.dbo.backupmediafamily  
   INNER JOIN msdb.dbo.backupset ON msdb.dbo.backupmediafamily.media_set_id = msdb.dbo.backupset.media_set_id   
--Enter your database below
--and database_name = 'db_name_here'
and msdb.dbo.backupset.backup_start_date>'2013-12-31' and msdb.dbo.backupset.backup_start_date<'2014-01-27 23:59:59'
ORDER BY  
   msdb.dbo.backupset.database_name, 
   msdb.dbo.backupset.backup_start_date

Gibt es eine Möglichkeit, diese Informationen durch Ändern meines Codes zu erhalten? Ich kann den Verlauf von JOB1 abrufen, indem ich eine SQL-Anweisung ausführe, die für die Tabelle sysjobhistory und sysjob ausgeführt wird. Dies kann ein langer Weg sein Gibt es eine Möglichkeit, die Tabellen sysjobhistory, sysjob, backupset und backupsetmediafamily in msdb zu verwenden, um die gewünschten Ergebnisse zu erzielen?

iamZel
quelle

Antworten:

15

Enthält backupsetleider keine fehlgeschlagenen Sicherungen, und ich weiß nicht, woanders in msdbdiesen möglicherweise gespeichert werden, es sei denn, Sie können sich darauf verlassen sysjobhistory, dass nicht alle Zeit (abhängig von Ihren Aufbewahrungseinstellungen) und welche ignoriert werden Sicherungsversuche, die außerhalb des Kontexts eines Jobs durchgeführt wurden und die - im Fall eines Jobs, der viele Datenbanken sichert - keine Differenzierung darüber liefern würden, welche Datenbank tatsächlich fehlgeschlagen ist, es sei denn, dies geschah zu Beginn des Jobs - dies ist weil die Nachrichten ziemlich ausführlich sind, aber abgeschnitten werden.

Wenn Sie absolut wissen, dass Job nnur die eine Datenbank gesichert wird und dass jeder Fehler dieses Jobs bedeutet, dass die Datenbank nicht gesichert wurde (da der Job auch nach erfolgreicher Sicherung fehlschlagen kann, z. B. wenn versucht wird, ihn zu verkleinern oder andere Wartungsarbeiten durchzuführen), dann könnten Sie eine Abfrage wie diese verwenden:

DECLARE @job SYSNAME, @db SYSNAME;

SELECT @job = N'Job 1', @db = N'db_name';

SELECT  
   bs.database_name,  
   bs.backup_start_date,  
   bs.backup_finish_date, 
   [Total Time] = CAST((DATEDIFF(SECOND, bs.backup_start_date,bs.backup_finish_date))
     AS VARCHAR(30))+ ' secs',
   CAST(bs.backup_size/1024/1024 AS NUMERIC(10,2)) AS 'Backup Size(MB)',   
   h.[message]
FROM msdb.dbo.sysjobhistory AS h
INNER JOIN msdb.dbo.sysjobs AS j
ON h.job_id = j.job_id
AND h.step_id = 0
LEFT OUTER JOIN msdb.dbo.backupset AS bs
ON bs.database_name = @db
AND ABS(DATEDIFF(SECOND, bs.backup_start_date, CONVERT(DATETIME,CONVERT(CHAR(8), h.run_date) 
  + ' ' + STUFF(STUFF(RIGHT('0'+CONVERT(VARCHAR(6),h.run_time),6),3,0,':'),6,0,':')))) < 5
WHERE j.name = @job
ORDER BY bs.backup_start_date;

Ja, es ist wirklich hässlich, weil es sysjobhistoryin SQL Server 2014 sogar speichert run_dateund run_timeals separate Ganzzahlen. Ich wette, wer auch immer diese Entscheidung getroffen hat, befindet sich immer noch im Hintergrund von Dartscheiben im gesamten Gebäude 35. Es wird auch davon ausgegangen, dass das Backup der allererste Schritt in diesem Job ist, daher der weniger als wissenschaftliche Vergleich von Datum und Uhrzeit, um sicherzustellen, dass wir richtig sind korrelierte die richtige Instanz des Jobs mit der richtigen Instanz der Sicherung. Oh, wie gerne könnte ich das Schema für Backups und Jobs neu gestalten.

Wenn Sie einen größeren Bereich außerhalb des Jobs wünschen, können Sie im SQL Server-Fehlerprotokoll nach fehlgeschlagenen Sicherungen suchen (sofern diese nicht entfernt wurden):

EXEC sp_readerrorlog 0, 1, 'BACKUP failed'; -- current
EXEC sp_readerrorlog 1, 1, 'BACKUP failed'; -- .1 (previous)
EXEC sp_readerrorlog 2, 1, 'BACKUP failed'; -- .2 (the one before that)
....

(Aber ich kenne keine gute und einfache Möglichkeit, diese Ausgabe in Ihre vorhandene Abfrage zu integrieren.)

Sie können auch "fehlende" erfolgreiche Sicherungen aus der Standardablaufverfolgung korrelieren, z

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 dt.DatabaseName, dt.StartTime, bs.backup_start_date, bs.backup_finish_date, 
  [Status] = CASE WHEN bs.backup_start_date IS NULL 
    THEN 'Probably failed'
    ELSE 'Seems like success'
  END
FROM sys.fn_trace_gettable(@path, DEFAULT) AS dt
LEFT OUTER JOIN msdb.dbo.backupset AS bs
ON dt.DatabaseName = bs.database_name
AND ABS(DATEDIFF(SECOND, dt.StartTime, bs.backup_start_date)) < 5
WHERE dt.EventClass = 115 -- backup/restore events
AND UPPER(CONVERT(NVARCHAR(MAX),dt.TextData)) LIKE N'BACKUP%DATABASE%'
--AND dt.DatabaseName = N'db_name' -- to filter to a single database
--AND bs.database_name = N'db_name'
ORDER BY dt.StartTime;

Dies hängt natürlich auch davon ab, dass die Daten aus dem Standard-Trace weglaufen, der Datenbankname sich nicht geändert hat usw. Leider unterscheidet der Standard-Trace nicht zwischen erfolgreichen und fehlgeschlagenen Sicherungen, und die Startzeit stimmt nicht genau mit der MSDB überein Daten, aber solange Sie keine Backups in einer Schleife ausführen, sollte dies für Augäpfel in Ordnung sein. Ich habe versucht, diese Probleme in die Abfrage einzubeziehen.

Schließlich möchten Sie möglicherweise eine FULL OUTER JOINdort verwenden, falls das Backupset einen längeren Verlauf als die Standardablaufverfolgung hat. Dies ändert die Semantik von [Status]leicht.

Vielleicht möchten Sie auch dieses böse Ding ausprobieren , obwohl ich nicht viel Glück damit hatte. Ich konnte nur den aktuellen oder den neuesten Status anzeigen, sodass dies nur hilfreich war, wenn der Job beim letzten Ausführen fehlschlug, und - wie sysjobhistory- keine Informationen über Sicherungen erhalten konnte, die versucht wurden, jedoch nicht über einen Job.

Aaron Bertrand
quelle
Vielen Dank für die ausführliche Erklärung, aber ich erhalte eine Fehlermeldung, wenn ich die erste Abfrage ausführe. Meldung 139, Ebene 15, Status 1, Zeile 0 Einer lokalen Variablen kann kein Standardwert zugewiesen werden. Nachricht 137, Ebene 15, Status 2, Zeile 16 Muss die skalare Variable "@db"
deklarieren
@iamZel dann bist du auf SQL Server 2005, nicht auf SQL Server 2008.
Aaron Bertrand
Ja, ich bin. Das habe ich vergessen zu erwähnen. Ich bin auf SQL2K5
iamZel
1
@iamZel Der Grund, warum ich dachte, Sie wären auf SQL Server 2008, ist, dass Sie Ihre Frage mit dieser Version versehen haben. Bitte sorgfältig markieren.
Aaron Bertrand
sp_readerrorlog ist gut genug für mich. Vielen Dank Aaron
iamZel