Запрос, который отображает информацию о резервном копировании (успешно и не удалось) SQL Server

9

У меня есть две работы, которые поддерживают две разные базы данных. Резервное копирование
задания 1 для DB1 Резервное копирование
задания 2 Не

удается выполнить резервное копирование DB2 DB1 из-за нехватки места на диске 1 в результате сбоя задания 1. Чтобы решить эту проблему, мне просто нужно было добавить место. Нет, важная персона. Мне сказали об этом сегодня, когда проблема произошла в течение месяца. Да, я знаю, что это безумие, но это разработчик


Я хочу получить полную историю резервного копирования для DB1. Я знаю, что могу получить информацию об успешном резервном копировании из таблицы msdb.dbo.backupset, но я хочу знать, есть ли запрос, отображающий сбойные резервные копии для базы данных.

Мой запрос ниже отображает историю резервного копирования для конкретной базы данных от 12/31 / 13-1 / 27/14. Информация включает в себя сервер, имя базы данных, время начала и окончания резервного копирования, общее время, необходимое для резервного копирования базы данных, размер базы данных и имя набора резервных копий.

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

Есть ли способ получить эту информацию, изменив мой код? Я могу получить историю JOB1, выполнив оператор sql, который работает с таблицей sysjobhistory и sysjob. Это может быть долгий путь. Можно ли использовать таблицы sysjobhistory, sysjob, backupset и backupsetmediafamily в msdb для получения желаемых результатов?

iamZel
источник

Ответы:

15

К сожалению, 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не смог получить информацию о любых попытках резервного копирования, но не через задание.

Аарон Бертран
источник
Большое спасибо за подробное объяснение, но я получаю сообщение об ошибке при выполнении первого запроса. Сообщение 139, уровень 15, состояние 1, строка 0 Невозможно присвоить значение по умолчанию локальной переменной. Сообщение 137, Уровень 15, Состояние 2, Строка 16 Необходимо объявить скалярную переменную "@db"
iamZel
@iamZel, тогда вы находитесь на SQL Server 2005, а не на SQL Server 2008.
Аарон Бертран
Да. Я забыл упомянуть об этом. Я на SQL2K5
iamZel
1
@iamZel Причина, по которой я думал, что вы работаете на SQL Server 2008, заключается в том, что вы пометили свой вопрос этой версией. Пожалуйста, отметьте внимательно.
Аарон Бертран
sp_readerrorlog достаточно хорош для меня. Большое спасибо Aaron
iamZel