Consulta que exibe informações de backup (bem-sucedidas e com falha) SQL Server

9

Eu tenho dois trabalhos que fazem backup de dois bancos de dados diferentes.
O trabalho 1 faz backup do DB1 O
trabalho 2 faz backup do DB2

DB1 falha ao fazer o backup devido ao pouco espaço na Unidade 1, resultante de uma falha do trabalho 1. Para corrigir esse problema, eu apenas tive que adicionar espaço. Nada demais. Fui informado sobre isso hoje, quando o problema ocorre há um mês. Sim, eu sei que é loucura, mas é dev


Desejo obter um histórico completo de backup do DB1. Sei que posso recuperar informações de backup bem-sucedidas da tabela msdb.dbo.backupset, mas quero saber se existe uma consulta que exibe backups com falha de um banco de dados.

Minha consulta abaixo exibe o histórico de backup de um banco de dados específico de 12/31 / 13-1 / 27/14. As informações incluem servidor, nome do banco de dados, horário de início e término do backup, tempo total necessário para o backup dos dbs, tamanho do db e nome do conjunto de backup.

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

Existe alguma maneira de obter essas informações modificando meu código? Eu sou capaz de recuperar o histórico do JOB1 executando uma instrução sql que é executada na tabela sysjobhistory e sysjob. Isso pode ser um tiro no escuro Existe uma maneira de usar as tabelas sysjobhistory, sysjob, backupset e backupsetmediafamily no msdb para produzir os resultados desejados?

iamZel
fonte

Respostas:

15

Infelizmente, backupsetele não contém backups com falha, e eu não conheço nenhum outro local onde msdbeles podem ser armazenados, a menos que você possa confiar sysjobhistory, que não contém todo o tempo (dependendo das configurações de retenção) e que ignoraria qualquer tentativas de backup que foram feitas fora do contexto de um trabalho e que - no caso de um backup de muitos bancos de dados - não forneceriam diferenciação sobre qual banco de dados realmente falhou, a menos que acontecesse no início do trabalho - isso é porque as mensagens são bastante detalhadas, mas são truncadas.

Se você sabe absolutamente que Job napenas faz backup de um banco de dados e que todas as falhas desse trabalho significam que não foi feito backup do banco de dados (já que o trabalho também pode falhar após o backup ter sido bem-sucedido, por exemplo, tentando reduzir ou executar outra manutenção), então você pode usar uma consulta como esta:

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;

Sim, é realmente feio, porque sysjobhistory, mesmo no SQL Server 2014, armazena run_datee run_timecomo números inteiros separados. Aposto que quem tomou essa decisão ainda está no pano de fundo dos dardos em todo o edifício 35. Ele também pressupõe que o backup seja o primeiro passo no trabalho, portanto, a comparação de data / hora menos do que científica para garantir que estamos devidamente correlacionou a instância correta do trabalho à instância correta do backup. Ah, como eu gostaria de poder redesenhar o esquema para backups e trabalhos.

Se você deseja um escopo mais amplo fora do trabalho, pode procurar backups com falha no log de erros do SQL Server (se eles não tiverem sido alternados):

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)
....

(Mas não conheço uma maneira fácil e agradável de incorporar essa saída à sua consulta existente.)

Você também pode correlacionar backups bem-sucedidos "ausentes" do rastreamento padrão, por exemplo,

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;

É claro que isso também conta com os dados do rastreamento padrão, o nome do banco de dados não foi alterado etc. dados, mas desde que você não esteja executando backups em um loop, isso pode ser bom para os olhos. Eu tentei incorporar esses problemas na consulta.

Por fim, convém usar um FULL OUTER JOINlá, caso o conjunto de backup tenha um histórico mais longo que o rastreamento padrão. Isso muda a semântica de [Status]ligeiramente.

Você também pode tentar essa coisa desagradável , embora eu não tenha tido muita sorte com isso. Eu só consegui ver o status atual ou mais recente, de modo que só ajudou quando o trabalho falhou na última vez em que foi executado e - como sysjobhistory- não foi possível obter informações sobre backups que foram tentados, mas não através de um trabalho.

Aaron Bertrand
fonte
Muito obrigado pela explicação detalhada, mas recebo um erro ao executar a primeira consulta. Msg 139, Nível 15, Estado 1, Linha 0 Não é possível atribuir um valor padrão a uma variável local. Msg 137, Nível 15, Estado 2, Linha 16 Deve declarar a variável escalar "@db"
iamZel
@iamZel, então você está no SQL Server 2005, e não no SQL Server 2008.
Aaron Bertrand
Sim, eu sou. Eu esqueci de mencionar isso. Estou no SQL2K5
iamZel 30/01
11
@iamZel A razão pela qual pensei que você estava no SQL Server 2008 é porque marcou sua pergunta com essa versão. Por favor, marque com cuidado.
Aaron Bertrand
sp_readerrorlog é bom o suficiente para mim. Muito obrigado Aaron
iamZel