sql >> Databáze >  >> RDS >> Database

Vyhrazená uložená procedura pro získání nejnovějšího stavu záloh databáze

Jakýkoli SQL Server DBA (samozřejmě to platí pro všechny platformy) bude souhlasit s tím, že zálohování databází je pro datové profesionály to nejdůležitější. Sledování stavu těchto záloh je zásadní. Aby byl tento úkol jednodušší, vytvořil jsem vlastní uloženou proceduru. Umožní vám získat nejnovější stavy záloh databází (pokud existují) pro všechny potřebné databáze ve vaší péči.

Než začneme, zkontrolujte účet spouštějící tuto uloženou proceduru. Aby bylo možné vytvořit uloženou proceduru, musí mít potřebná práva k provedení SELECT v následujících tabulkách:

  • sys.databases (master)
  • backupmediafamily (msdb)
  • backupset (msdb)

Jak používat uloženou proceduru

Kód T-SQL uložené procedury je uveden v tomto článku. Procedura očekává 2 parametry:

  • @databáze je název cílové databáze. Pokud není zadána žádná, budou se předpokládat všechny databáze.
  • @backupType je typ zálohy, kterou chcete zkontrolovat. V závislosti na vaší situaci to může být:
    • F – Plný
    • D – Diferenciál
    • L – Protokol transakcí
    • A – Vše výše uvedené

Zde je matice možných kombinací parametrů, které lze použít, a výstup, který byste měli očekávat. X je název databáze, na kterou chcete cílit.

@databáze @backupType Výstup
Vše A Zobrazuje nejnovější úplné, rozdílové a transakční zálohy všech databází v rámci instance.
Vše F Zobrazuje nejnovější úplné zálohy všech databází v rámci instance.
Vše D Zobrazuje nejnovější rozdílové zálohy všech databází v rámci instance.
Vše L Zobrazuje nejnovější zálohy protokolu transakcí všech databází v rámci instance.
X A Zobrazuje nejnovější úplné, rozdílové a transakční zálohy databáze X v rámci instance.
X F Zobrazuje nejnovější úplnou zálohu databáze X v rámci instance.
X D Zobrazuje nejnovější rozdílovou zálohu databáze X v rámci instance.
X L Zobrazuje nejnovější zálohu protokolu transakcí databáze X v rámci instance.

Poznámka :Pokud je cílová databáze v modelu Simple Recovery Model, informace o zálohách protokolu transakcí se zobrazí jako NULL. Nikdy to nebylo v rámci modelu úplné obnovy a záloha protokolu transakcí u něj nikdy neproběhla.

Testy provedení

Předvedu vám některé kombinace skriptů, abyste získali představu o tom, co lze od této uložené procedury očekávat:

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'

Snímky obrazovky nebudou pokrývat SP zacílený na jednu databázi, protože výstup je stejný, jediný rozdíl je v tom, že zobrazuje jednu databázi.

Jak vidíte, data pro sloupce „Diferenciální“ jsou NULL, protože jsem nikdy pro žádný z nich nevytvářel rozdílovou zálohu. Abychom však plně ukázali, jak užitečné toto řešení může být, potřebujeme rozdílovou zálohu. Vezmu jeden pro databázi DBA a provedu uloženou proceduru, abych viděl, co vrátí:

EXEC DBA_DatabaseBackups @database = 'DBA', @backupType = 'D'

Po vytvoření rozdílové zálohy můžete vidět, že naše uložená procedura vrací také data pro rozdílové sloupce, přesně z té zálohy, kterou jsem právě vytvořil.

Úplný kód uložené procedury

Na samém začátku skriptu uvidíte výchozí hodnoty – skript je předpokládá, pokud pro každý parametr není předána žádná hodnota.

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

Závěr

Pomocí této vlastní uložené procedury můžete sestavit mechanismus, který vás upozorní, když určitý typ zálohy pro danou databázi nebyl v určitém období vytvořen.

Tuto uloženou proceduru můžete nasadit v každé instanci SQL Serveru a zkontrolovat informace o zálohách pro každou jednotlivou databázi (systémové a uživatelské databáze).

Informace vrácené uloženou procedurou můžete také použít k vytvoření mapy záloh k identifikaci umístění nejnovějšího záložního souboru pro každou databázi. Ve své současné práci jsem to použil k vytvoření skriptu pro organizaci testů obnovy všech záloh pod mou podporou a potvrzení, že jsou 100% spolehlivé. Pro mě to bylo nesmírně užitečné.


  1. Zpětné skenování indexu SQL Server:Porozumění a ladění výkonu

  2. Jak vytvořit hierarchický rekurzivní dotaz MySQL?

  3. Více SQL, méně kódu, s PostgreSQL

  4. Jaký je rozdíl mezi použitím křížového spojení a vložením čárky mezi dvě tabulky?