Purtroppo, backupset
non contiene backup non riusciti e non sono a conoscenza di nessun altro in msdb
questi casi che può essere archiviato, a meno che tu non possa fare affidamento su di esso sysjobhistory
, che non contiene sempre (a seconda delle impostazioni di conservazione) e che ignorerebbe qualsiasi i tentativi di backup effettuati al di fuori del contesto di un lavoro e che - nel caso di un lavoro che esegue il backup di molti database - non fornirebbero una differenziazione su quale database sia effettivamente fallito, a meno che non sia accaduto all'inizio del lavoro - questo è perché la messaggistica è piuttosto dettagliata ma viene troncata.
Se si sa assolutamente che Job n
esegue il backup del solo database e che ogni errore di quel processo significa che non è stato eseguito il backup del database (poiché il processo potrebbe anche fallire dopo il backup riuscito, ad esempio tentando di ridurre o eseguire altri interventi di manutenzione), allora potresti usare una query come questa:
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 decimal(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(char(6),h.run_time),6),3,0,':'),6,0,':')))) < 5
WHERE j.name = @job
ORDER BY bs.backup_start_date;
Sì, è davvero brutto, perché sysjobhistory
ancora, anche in SQL Server 2014, memorizza run_date
e run_time
come numeri interi separati. Scommetto che chiunque abbia preso questa decisione è ancora sullo sfondo di freccette in tutto l'edificio 35. Presuppone anche che il backup sia il primo passo nel lavoro, quindi il confronto data / ora piuttosto meno scientifico per assicurarsi che abbiamo correttamente correlata l'istanza corretta del lavoro all'istanza corretta del backup. Oh, come vorrei poter ridisegnare lo schema per backup e lavori.
Se si desidera un ambito più ampio al di fuori del processo, è possibile cercare backup non riusciti nel registro errori di SQL Server (se non sono stati eliminati ciclicamente):
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)
....
(Ma non conosco un modo semplice e piacevole per incorporare quell'output nella tua query esistente.)
È inoltre possibile correlare backup riusciti "mancanti" dalla traccia predefinita, ad es
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;
Naturalmente questo si basa anche sui dati della traccia predefinita che si sposta ciclicamente, sul nome del database che non è stato modificato, ecc. E sfortunatamente, la traccia predefinita non distingue tra backup riusciti e falliti e l'ora di inizio non corrisponderà esattamente all'MSDB dati, ma fintanto che non si eseguono backup in un ciclo, questo dovrebbe andare bene per il bulbo oculare. Ho provato a incorporare questi problemi nella query.
Infine, potresti voler utilizzare un FULL OUTER JOIN
lì, nel caso in cui il set di backup abbia una cronologia più lunga rispetto alla traccia predefinita. Questo cambia [Status]
leggermente la semantica di .
Potresti anche provare questa brutta cosa , anche se non ho avuto molta fortuna. Sono stato in grado di vedere solo lo stato corrente o più recente, in modo che mi sia stato d'aiuto solo quando il lavoro è fallito l'ultima volta che è stato eseguito e - come sysjobhistory
- non sono stato in grado di ottenere informazioni su eventuali backup che sono stati tentati ma non attraverso un lavoro.