Qualquer DBA do SQL Server (claro, isso se aplica a todas as plataformas) concordará que os backups de banco de dados são as coisas mais essenciais para os profissionais de dados. Monitorar os status desses backups é crucial. Para tornar essa tarefa mais simples, criei um procedimento armazenado personalizado. Ele permitirá que você obtenha os status dos backups de banco de dados mais recentes (se houver) para todos os bancos de dados necessários sob seus cuidados.
Antes de começarmos, verifique a conta que está executando este procedimento armazenado. Ele deve ter os direitos necessários para executar SELECT nas seguintes tabelas para criar o procedimento armazenado:
- sys.databases (mestre)
- família de mídia de backup (msdb)
- backupset (msdb)
Como usar o procedimento armazenado
O código T-SQL do procedimento armazenado é fornecido neste artigo. O procedimento espera 2 parâmetros:
- @banco de dados é o nome do banco de dados de destino. Se nenhum for especificado, todos os bancos de dados serão assumidos.
- @backupType é o tipo de backup que você deseja verificar. Dependendo da sua situação, pode ser:
- F – Completo
- D – Diferencial
- E – Registro de transações
- A – Todas as opções acima
Aqui está uma matriz de possíveis combinações de parâmetros que podem ser usadas e a saída que você deve esperar. X é o nome do banco de dados que você deseja segmentar.
@database | @backupType | Saída |
Todos | A | Exibe os backups completos, diferenciais e de log de transações mais recentes de todos os bancos de dados na instância. |
Todos | F | Exibe os backups completos mais recentes de todos os bancos de dados na instância. |
Todos | D | Exibe os backups diferenciais mais recentes de todos os bancos de dados na instância. |
Todos | L | Exibe os backups de log de transações mais recentes de todos os bancos de dados na instância. |
X | A | Exibe os backups completos, diferenciais e de log de transações mais recentes do banco de dados X na instância. |
X | F | Exibe o backup completo mais recente do banco de dados X dentro da instância. |
X | D | Exibe o backup diferencial mais recente do banco de dados X dentro da instância. |
X | L | Exibe o backup de log de transações mais recente do banco de dados X na instância. |
Observação :Se o banco de dados de destino estiver no Modelo de Recuperação Simples, as informações de backups do log de transações aparecerão como NULL. Ele nunca esteve sob o modelo de recuperação completa e o backup do log de transações nunca ocorreu para ele.
Testes de execução
Vou demonstrar algumas das combinações de scripts para você ter uma ideia do que esperar deste Stored Procedure:
EXEC DBA_DatabaseBackups @database = 'All', @backupType = 'A'
EXEC DBA_DatabaseBackups @database = 'All', @backupType = 'F'
EXEC DBA_DatabaseBackups @database = 'All', @backupType = 'D'
EXEC DBA_DatabaseBackups @database = 'All', @backupType = 'L'
As capturas de tela não abrangerão o SP direcionado a um único banco de dados porque a saída é a mesma, a única diferença é que ele exibe um banco de dados.
Como você pode ver, os dados das colunas “Diferenciais” são NULL porque nunca fiz backup diferencial para nenhuma delas. No entanto, para demonstrar completamente o quão útil essa solução pode ser, precisamos de um backup diferencial. Vou pegar um para o banco de dados DBA e executar o procedimento armazenado para ver o que ele retorna:
EXEC DBA_DatabaseBackups @database = 'DBA', @backupType = 'D'
Depois de fazer o backup diferencial, você pode ver que nosso procedimento armazenado retorna os dados para as colunas Diferenciais também, justamente do backup que acabei de fazer.
O Código de Procedimento Armazenado Completo
No início do script, você verá os valores padrão – o script os assume se nenhum valor for passado para cada parâmetro.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Alejandro Cobar
-- Create date: 2021-05-10
-- Description: SP to retrieve the latest backups information
-- =============================================
CREATE PROCEDURE DBA_DatabaseBackups
@database VARCHAR(256) = 'all',
@backupType CHAR(1) = 'A'
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sqlCommand VARCHAR(MAX);
SET @sqlCommand = '
WITH MostRecentBackups
AS(
SELECT
database_name AS [Database],
MAX(bus.backup_finish_date) AS LastBackupTime,
CASE bus.type
WHEN ''D'' THEN ''Full''
WHEN ''I'' THEN ''Differential''
WHEN ''L'' THEN ''Transaction Log''
END AS Type
FROM msdb.dbo.backupset bus
WHERE bus.type <> ''F''
GROUP BY bus.database_name,bus.type
),
BackupsWithSize
AS(
SELECT
mrb.*,
(SELECT TOP 1 CONVERT(DECIMAL(10,4), b.compressed_backup_size/1024/1024/1024) AS backup_size FROM msdb.dbo.backupset b WHERE [Database] = b.database_name AND LastBackupTime = b.backup_finish_date) AS [Backup Size],
(SELECT TOP 1 DATEDIFF(s, b.backup_start_date, b.backup_finish_date) FROM msdb.dbo.backupset b WHERE [Database] = b.database_name AND LastBackupTime = b.backup_finish_date) AS [Seconds],
(SELECT TOP 1 b.media_set_id FROM msdb.dbo.backupset b WHERE [Database] = b.database_name AND LastBackupTime = b.backup_finish_date) AS media_set_id
FROM MostRecentBackups mrb
)
SELECT
d.name AS [Database],
d.state_desc AS State,
d.recovery_model_desc AS [Recovery Model],'
IF @backupType = 'F' OR @backupType = 'A'
SET @sqlCommand += '
bf.LastBackupTime AS [Last Full],
DATEDIFF(DAY,bf.LastBackupTime,GETDATE()) AS [Time Since Last Full (in Days)],
bf.[Backup Size] AS [Full Backup Size],
bf.Seconds AS [Full Backup Seconds to Complete],
(SELECT TOP 1 bmf.physical_device_name FROM msdb.dbo.backupmediafamily bmf WHERE bmf.media_set_id = bf.media_set_id AND bmf.device_type = 2) AS [Full Backup Path]
'
IF @backupType = 'A'
SET @sqlCommand += ','
IF @backupType = 'D' OR @backupType = 'A'
SET @sqlCommand += '
bd.LastBackupTime AS [Last Differential],
DATEDIFF(DAY,bd.LastBackupTime,GETDATE()) AS [Time Since Last Differential (in Days)],
bd.[Backup Size] AS [Differential Backup Size],
bd.Seconds AS [Diff Backup Seconds to Complete],
(SELECT TOP 1 bmf.physical_device_name FROM msdb.dbo.backupmediafamily bmf WHERE bmf.media_set_id = bd.media_set_id AND bmf.device_type = 2) AS [Diff Backup Path]
'
IF @backupType = 'A'
SET @sqlCommand += ','
IF @backupType = 'L' OR @backupType = 'A'
SET @sqlCommand += '
bt.LastBackupTime AS [Last Transaction Log],
DATEDIFF(MINUTE,bt.LastBackupTime,GETDATE()) AS [Time Since Last Transaction Log (in Minutes)],
bt.[Backup Size] AS [Transaction Log Backup Size],
bt.Seconds AS [TLog Backup Seconds to Complete],
(SELECT TOP 1 bmf.physical_device_name FROM msdb.dbo.backupmediafamily bmf WHERE bmf.media_set_id = bt.media_set_id AND bmf.device_type = 2) AS [Transaction Log Backup Path]
'
SET @sqlCommand += '
FROM sys.databases d
LEFT JOIN BackupsWithSize bf ON (d.name = bf.[Database] AND (bf.Type = ''Full'' OR bf.Type IS NULL))
LEFT JOIN BackupsWithSize bd ON (d.name = bd.[Database] AND (bd.Type = ''Differential'' OR bd.Type IS NULL))
LEFT JOIN BackupsWithSize bt ON (d.name = bt.[Database] AND (bt.Type = ''Transaction Log'' OR bt.Type IS NULL))
WHERE d.name <> ''tempdb'' AND d.source_database_id IS NULL'
IF LOWER(@database) <> 'all'
SET @sqlCommand += ' AND d.name ='+CHAR(39)[email protected]+CHAR(39)
EXEC (@sqlCommand)
END
GO
Conclusão
Com esse procedimento armazenado personalizado, você pode criar um mecanismo para alertá-lo quando um determinado tipo de backup para um determinado banco de dados não for feito em um determinado período.
Você pode implantar esse procedimento armazenado em cada instância do SQL Server e verificar as informações de backup para cada banco de dados (bancos de dados do sistema e do usuário).
Além disso, você pode usar as informações retornadas pelo procedimento armazenado para criar um mapa de backup para identificar o local do arquivo de backup mais recente para cada banco de dados. Em meu trabalho atual, usei isso para criar um script para orquestrar os testes de restauração de todos os backups sob meu suporte e confirmar que eles são 100% confiáveis. Para mim, foi extremamente útil.