К сожалению, backupset
не содержит сбойных резервных копий, и я не знаю, где еще msdb
они могут храниться, если только вы не можете положиться на них sysjobhistory
, которые не содержат все время (в зависимости от ваших настроек хранения) и которые игнорируют любые Попытки резервного копирования, которые были сделаны вне контекста задания и которые - в случае задания, которое выполняет резервное копирование многих баз данных - не обеспечили бы различие в том, какая база данных фактически потерпела неудачу, если только это не произошло в самом начале задания - это потому что сообщения довольно многословны, но усечены.
Если вы точно знаете, что Job n
выполняется резервное копирование только одной базы данных, и что каждый сбой этого задания означает, что резервное копирование базы данных не выполнялось (поскольку задание также может завершиться ошибкой после успешного резервного копирования, например, при попытке сжать или выполнить другое обслуживание), тогда вы можете использовать такой запрос:
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;
Да, это действительно ужасно, потому что sysjobhistory
в SQL Server 2014 все еще хранятся run_date
иrun_time
как отдельные целые числа. Бьюсь об заклад, кто бы ни принял это решение, он все еще находится на фоне дартс во всем здании 35. Он также предполагает, что резервное копирование - это самый первый шаг в работе, следовательно, сравнительно меньше, чем научное сравнение даты / времени, чтобы убедиться, что мы правильно сопоставил правильный экземпляр задания с правильным экземпляром резервной копии. О, как бы мне хотелось изменить схему для резервных копий и заданий.
Если вам нужна более широкая область действия за пределами задания, вы можете искать сбойные резервные копии в журнале ошибок SQL Server (если они не были зациклены):
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)
....
(Но я не знаю хорошего и простого способа включить этот вывод в существующий запрос.)
Вы также можете соотнести «отсутствующие» успешные резервные копии с трассировкой по умолчанию, например
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;
Конечно, это также зависит от циклического удаления данных из трассировки по умолчанию, имени базы данных не изменилось и т. Д. И, к сожалению, трассировка по умолчанию не различает успешное и неудачное резервное копирование, и время запуска не будет точно соответствовать MSDB данные, но пока вы не запускаете резервные копии в цикле, это должно быть хорошо для глазного яблока. Я пытался включить эти вопросы в запрос.
Наконец, вы можете использовать FULL OUTER JOIN
там, если набор резервных копий имеет более длинную историю, чем трассировка по умолчанию. Это [Status]
немного меняет семантику .
Вы также можете попробовать эту неприятную вещь , хотя мне не очень повезло с этим. Я мог видеть только текущий или самый последний статус, так что это помогло только в случае сбоя задания в последний раз, когда он выполнялся, и, как, например, sysjobhistory
не смог получить информацию о любых попытках резервного копирования, но не через задание.