Introduktion
Under de senaste två eller tre månaderna har jag två gånger blivit tillfrågad om en lösning som är inbyggd i SQL Server som konsoliderar en säkerhetskopieringsrapport för flera SQL Server-instanser i ett företag. Den här frågan kom från vänner som inte nödvändigtvis ville spendera pengar på att köpa ett verktyg men som var mer benägna att utnyttja funktionerna i SQL Server. Jag har tänkt på två möjliga sätt att uppnå detta:
- Använda länkade servrar, katalogvyer, SQL-agentjobb och databaspost
- Använda Central Management Server
I den här artikeln kommer jag att demonstrera den första och hoppas att vi får en andra del av artikeln någon gång senare.
Scenario
Min miljö består av en uppsättning av tre instanser som sitter på separata servrar på AWS. Dessa "servrar" är faktiskt Amazon EC2s som kör SQL Server 2017 RTM CU5. Vi kommer också att dra nytta av Amazon Simple Email Service för att konfigurera Databas Mail. I produktionen kan du definitivt använda dina lokala e-postservrar och uppnå samma mål. Du kommer att märka senare i den här artikeln att värdnamnet (och därmed instansnamnen) är desamma. Detta beror på att servrarna klonades från samma Amazon Machine Image (ursäkta "latheten"). Detta kommer sannolikt inte att vara fallet i produktionen.
Ta några säkerhetskopior
Låt oss börja med att ta några säkerhetskopior av databaser som sitter på dessa tre instanser. Detta kommer att generera den data vi ska arbeta med. Vi ska sedan verifiera att säkerhetskopiorna finns i systemtabellerna msdb.dbo.backupset och msdb.dbo.backupmediafamily . De fullständiga beskrivningarna av dessa tabeller kan granskas i denna Microsoft-dokumentation eller helt enkelt använda sp_columns .
-- Lista 1:Ta säkerhetskopior av instanserna-- Säkerhetskopiera en enda DB med en stripebackup-databas newdb till disk='newdb.bak'-- Säkerhetskopiera alla DB:er i instansen med tidsstämpel i backupsetet nameexec sp_MSforeachdb @command1='declare @path varchar(300)set @path=''M:\MSSQL\BACKUP\?_Backup'' + convert(varchar(10),getdate(),110) + ''.bak''skriv ut @pathbackup databas [?] till [email protected]'-- Säkerhetskopiera en enda stor DB med fyra stripesbackup-databas [PieceMealDB] todisk='M:\MSSQL\BACKUP\PieceMealDB_01.bak',disk='M:\MSSQL\BACKUP\PieceMealDB_02 .bak',disk='M:\MSSQL\BACKUP\PieceMealDB_03.bak',disk='M:\MSSQL\BACKUP\PieceMealDB_04.bak'withstats=10
Fig 3. Beskrivning av msdb.dbo.backupset
Kontrollera säkerhetskopior
Följande skript drar fördel av två katalogvyer backupset och backupmediafamily för att undersöka historiken för säkerhetskopior som skapats på en instans av SQL Server. Katalogen för backupset innehåller en rad för varje backupset. En säkerhetskopieringsuppsättning definieras som innehållet i en säkerhetskopieringsoperation som läggs till en mediauppsättning. En mediauppsättning är en beställningssamling av media som en eller flera säkerhetskopieringsoperationer har skrivits till.
-- Lista 2:Kontrollera säkerhetskopior med hjälp av msdb-tabeller --PRINT 'Kontrollera databaser som har säkerhetskopierats framgångsrikt'använd msdbgoselect bus.database_name,bus.type, case bus.type när 'D' sedan 'Full' när 'I' sedan 'Differential' när 'L' sedan 'Logg' slutar backup_type, bus.backup_start_date, bus.backup_finish_date,(((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date))*3600) + (((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +(((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date)) )[backup_time (secs)], bus.backup_size,bmf.physical_device_name från backupset busjoin backupmediafamily bmf på bus.media_set_id=bmf.media_set_idwhere bus.backup_start_date>=(getdate() - 7)order by bus.backup_start_dateFig 5. Exempel på utdata för säkerhetskopiering
Kontrollera säkerhetskopior på andra instanser
Med hjälp av länkade servrar kan vi extrahera data från fjärrinstanser. I det här fallet ska vi använda en enkel länkad server för att extrahera säkerhetskopieringshistorik från msdb-databaserna för två fjärrinstanser. Säkerhetskonfigurationen för dessa länkade servrar beror helt på dig, men vi har behållit den mycket enkel här för vårt mål. Lista 3 visar skriptet som kan använda dessa länkade servrar för att samla säkerhetskopieringshistorik.
Fig 6. En enkel länkad server
Fig 7. Länkad server för två fjärrinstanser
-- Lista 3:Kontrollera säkerhetskopior med hjälp av msdb-tabeller över länkade servrar använd msdbgowith srva as (välj instans av buss.servernamn, buss.databasnamn, buss.typ, fall bus.typ när 'D' sedan 'Full' när 'I' sedan 'Differential' när 'L' sedan 'Logg' slut backup_type, bus.backup_start_date, bus.backup_finish_date,(((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date))*3600) +(((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date) ))[backup_time (secs)], bus.backup_size,bmf.physical_device_name från backupset busjoin backupmediafamily bmf på bus.media_set_id=bmf.media_set_idwhere bus.backup_start_date>=(getdate() - 3)), srvb as_ (välj buss.namn) instans, bus.database_name,bus.type, case bus.type när 'D' sedan 'Full' när 'I' sedan 'Differential' när 'L' sedan 'Log' end backup_type, bus.backup_start_date, bus.backup_finish_date,( ((DATEPART(HH,bus.backup_finish_d åt))- (DATEPART(HH,bus.backup_start_date)))*3600) +(((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date))*60) +((( DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date)))[backup_time (secs)], bus.backup_size,bmf.physical_device_name from [10.0.1.155].msdb.dbo.backupset busjoin [10.0. 1.155].msdb.dbo.backupmediafamily bmf på bus.media_set_id=bmf.media_set_idwhere bus.backup_start_date>=(getdate() - 3)), srvc as (välj bus.server_name-instans, bus.database_name, bus.type, case bus .typ när 'D' sedan 'Full' när 'I' sedan 'Differential' när 'L' sedan 'Logg' slut backup_type, bus.backup_start_date, bus.backup_finish_date,(((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date)))*3600) +(((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date))*60) +(((DATEPART(SS, bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date)))[backup_time (secs)], bus.backup_size,bmf.physical_device_name från [10.0.1.83].ms db.dbo.backupset busjoin [10.0.1.83].msdb.dbo.backupmediafamily bmf på bus.media_set_id=bmf.media_set_idwhere bus.backup_start_date>=(getdate() - 3))välj * från srvaunion välj * från srvcbunsions;Inkluderar SES och Databas Mail
Nästa steg vi tar är att automatisera denna kontroll och skicka resultatuppsättningen till databasadministratörer. De steg som krävs skulle vara följande i sammanfattning:
- Konfigurera Amazon SES . Du kan lära dig hur du snabbt ställer in e-post på AWS med hjälp av dokumentationen som tillhandahålls på Amazon SES Quick Start. När du använder en lokal e-posttjänst är detta inte nödvändigt för DBA.
- Konfigurera Databas Mail . Den här artikeln är inte avsedd att demonstrera Databas Mail så vi ger bara en skärmdump av SQL-e-postkontokonfigurationen:
Fig 7. SQL Mail Account Settings
- Portnumret när du använder SES för att skicka e-post är 587 INTE 25
- Amazon SES kräver en säker anslutning, så kryssrutan som identifieras i lila (Fig. 7) måste vara markerad
- Grundläggande autentisering med SMTP-uppgifter krävs (dvs. anonym autentisering är inte tillåten).
Vi behöver bara vara medvetna om några saker när vi använder Amazon SES för Databas Mail:
- Konfigurera SQL Agent för att använda e-postprofilen . SQL Server Agent måste konfigureras för att använda e-postprofilen som skapades under konfigurationen av Databas Mail för att agentjobben ska skicka e-postmeddelanden. (Se fig. 8)
- Skapa en mellanställningstabell . En iscensättningstabell kommer att innehålla den aggregerade resultatuppsättningen för all säkerhetskopieringshistorik från de instanser som vi har riktat in oss på med länkade servrar. Tabellen DDL visas i lista 4.
-- Lista 4:Backuphistoriktabell DDLSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [dbo].[backuphistory]( [instans] [nvarchar](128) NULL, [databasnamn] [nvarchar](128) NULL, [typ [char](1) NULL, [backup_type] [varchar](12) NULL, [backup_start_date] [datetime] NULL, [backup_finish_date] [datetime] NULL, [backup_time (secs)] [int] NULL, [backup_size] [ numeric](20, 0) NULL, [physical_device_name] [nvarchar](260) NULL) PÅ [PRIMARY]GOFig 8. SQL Agent-inställningar
Vi går vidare och schemalägger skriptet i lista 3 i ett SQL Agent Job och vi har det fullständiga skriptet i Listing 5.
-- Lista 5:Slutför SQL Agent Job for Backup History NotificationUSE [msdb]GO/****** Objekt:Job [Enteprise Backup History Summary] Skriptdatum:2018-09-26 22:16:46 ******/BEGIN TRANSACTIONDECLARE @ReturnCode INTSELECT @ReturnCode =0/***** Objekt:JobCategory [[Okategoriserad (Lokal)]] Skriptdatum:2018-09-26 22:16:46 ** ****/OM INTE FINNS (VÄLJ namn FRÅN msdb.dbo.syscategories WHERE name=N'[Okategoriserad (Lokal)]' OCH category_class=1)BEGINEXEC @ReturnCode =msdb.dbo.sp_add_category @class=N'JOB' , @type=N'LOCAL', @name=N'[Okategoriserad (Lokal)]'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GÅ TILL AvslutaWithRollbackENDDECLARE @jobId BINARY(16)EXEC @ReturnCode =msdb. dbo.sp_add_job @job_name=N'Enteprise Backup History Summary', @enabled=1, @notify_level_eventlog=0, @notify_level_email=0, @notify_level_netsend=0, @notify_level_page=0, @Ndelete_level=0, @Nodescription beskrivning tillgänglig.', @category_name=N'[Okategoriserad (Lokal)]', @owner_login_name=N'TWE NTYTOWERS\Administrator', @job_id =@jobId OUTPUTIF (@@ERROR <> 0 ELLER @ReturnCode <> 0) GÅ TILL QuitWithRollback/****** Objekt:Steg [Aggregerad säkerhetskopieringshistorik] Skriptdatum:2018-09-26 22:16:46 ******/EXEC @ReturnCode =msdb.dbo.sp_add_jobstep @[email protected], @step_name=N'Aggregate Backup History', @step_id=1, @cmdexec_success_code=0, @ on_success_action=3, @on_success_step_id=0, @on_fail_action=2, @on_fail_step_id=0, @retry_attempts=0, @retry_interval=0, @os_run_priority=0, @subsystem=N'TSQL', @command=N'-- Kontrollera Säkerhetskopiering med hjälp av msdb-tabeller ---- Över länkade servrar använd msdbgotruncate-tabellen [msdb].[dbo].[backuphistory]; med srva som (välj instans av buss.servernamn, buss.databasnamn, buss.typ, fall buss.typ när '' D'' sedan ''Full'' när ''I'' sedan ''Differential'' när ''L'' sedan ''Logg'' slut backup_type, bus.backup_start_date, bus.backup_finish_date,(((DATEPART(HH) ,bus.backup_finish_date))- (DATEPART(HH,bus.backup_startdate)))*3600) +(((DATEPART(MI,bus.backup_fin) ish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +(((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date)))[backup_time (secs)], buss .backup_size,bmf.physical_device_name från backupset busjoin backupmediafamily bmf på bus.media_set_id=bmf.media_set_idwhere bus.backup_start_date>=(getdate() - 3)), srvb as (välj bus.server_name instans, bus.databas_name,bus. case bus.type när ''D'' sedan ''Full'' när ''I'' sedan ''Differential'' när ''L'' sedan ''Log'' end backup_type, bus.backup_start_date, bus.backup_finish_date ,(((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date)))*3600) +((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date) )))*60) +(((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_startdatum)))[backup_time (secs)], bus.backup_size,bmf.physical_device_name from [10.0.1.155] .msdb.dbo.backupset busjoin [10.0.1.155].msdb.dbo.backupmediafamily bmf på bus.media_set_id=bmf.media_set_idwhere b us.backup_start_date>=(getdate() - 3)), srvc as (välj bus.server_name-instans, bus.database_name,bus.type, case bus.type när ''D'' sedan ''Full'' när '' I'' sedan ''Differential'' när ''L'' sedan ''Logg'' slut backup_type, bus.backup_start_date, bus.backup_finish_date,(((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH, bus.backup_start_date)))*3600) +(((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +(((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_startdate)))[backup_time (secs)], bus.backup_size,bmf.physical_device_name from [10.0.1.83].msdb.dbo.backupset busjoin [10.0.1.83].msdb.family.bmfmedia på bus.media_set_id=bmf.media_set_idwhere bus.backup_start_date>=(getdate() - 3))infoga i [msdb].[dbo].[backuphistory]välj * från srvaunion välj * från srvbunionselect * från srvc;', @database_name =N'msdb', @flags=0IF (@@ERROR <> 0 OR @ReturnCode <> 0) GÅ TILL QuitWithRollback/****** Objekt:Steg [Fråga medlemsservrar för säkerhetskopior] Skriptdatum:2018-09-26 10:16:46 ******/EXEC @ReturnCode =msdb.dbo.sp_add_jobstep @[email protected], @step_name=N'Query Member Servers for Backups ', @step_id=2, @cmdexec_success_code=0, @on_success_action=3, @on_success_step_id=0, @on_fail_action=2, @on_fail_step_id=0, @retry_attempts=0, @retry_interval=0, @=0,_run N'TSQL', @command=N'DECLARE @tableHTML NVARCHAR(MAX);SET @tableHTML =N''Sammanfattning av företagssäkerhetskopiering
' ' + N''
Instansnamn | '' + N''Databasnamn | '' + N''Startdatum för säkerhetskopiering | '' + N''Säkerhetskopieringsslutdatum | '' + N''Säkerhetstid (sekunder) | '' + N''Säkerhetskopieringsstorlek | '' + N''Fysisk enhetsnamn |
---|
Tack och hälsningar,
Enterprise Database Operations
'';EXEC msdb.dbo.sp_send_dbmail @ recipients=''[email protected];[email protected]'', @subject =''Sammanfattning av företagsbackuphistorik'', @body =@tableHTML , @body_format =''HTML'';', @database_name=N'msdb', @flags=0IF (@@ERROR <> 0 ELLER @ReturnCode <> 0) GÅ TILL QuitWithRollback/****** Objekt:Steg [E-post slutfört resultat inställt på support] Skriptdatum:26/9/ 2018 10:16:46 PM ******/EXEC @ReturnCode =msdb.dbo.sp_add_jobstep @[email protected], @step_name=N'Mail Complete Result Set to Support', @step_id=3, @cmdexec_success_code =0, @on_success_action=1, @on_success_step_id=0, @on_fail_action=2, @on_fail_step_id=0, @retry_attempts=0, @retry_interval=0, @os_run_priority=0, @subsystem=N'TSQL', @command=N 'DECLARE @tableHTML NVARCHAR(MAX);SET @tableHTML =N''
Sammanfattning av företagssäkerhetskopiering
'' + N''Instansnamn | '' + N''Databasnamn | '' + N''Startdatum för säkerhetskopiering | '' + N''Säkerhetskopieringsslutdatum | '' + N''Säkerhetstid (sekunder) | '' + N''Säkerhetskopieringsstorlek | '' + N' 'Fysisk enhetsnamn |
---|
Tack och hälsningar,
Enterprise Database Operations
'';EXEC msdb.dbo.sp_send_dbmail @ recipients=''[email protected];[email protected]'', @subject =''Sammanfattning av företagsbackuphistorik'', @body =@tableHTML , @body_format =''HTML'';', @database_name=N'msdb', @flags=0IF (@@ERROR <> 0 ELLER @ReturnCode <> 0) GÅ TILL QuitWithRollbackEXEC @ReturnCode =msdb.dbo.sp_update_job @job_id =@jobId, @start_step_id =1OR (@ERROR) ELLER @ReturnCode <> 0) GÅ TILL QuitWithRollbackEXEC @ReturnCode =msdb.dbo.sp_add_jobserver @job_id =@jobId, @server_name =N'(local)'IF (@@ERROR <> 0 ELLER @ReturnCode TILL ÅTERGÅ ÅTERGÅ ÅTERKOMMANDE <> 0) EndSaveQuitWithRollback:IF (@@TRANCOUNT> 0) ROLLBACK TRANSACTIONEndSave:GO
Att utföra detta jobb resulterar i utdata som visas i Fig. 9. Tabellen skapas med mycket enkel HTML och kan vidareutvecklas för att passa dina behov.
Fig 9. E-postutdata för SQL Agent Job Execution
Slutsats
Vi har gått igenom en enkel metod för att aggregera säkerhetskopieringshistorik (och eventuellt annan data som finns i systemdatabaser) med hjälp av länkade servrar. Vi fortsatte vidare med att automatisera denna process med SQL Agent, Database Mail och lite HTML. Den här metoden kan tyckas lite grov och jag är säker på att det finns verktyg där ute som kan göra mycket bättre, men detta skulle vara ett serversyfte för de som precis har börjat med SQL Server eller miljöer med låg budget. Med lite kreativitet kan du anpassa skripten ytterligare och anpassa skripten till andra användningsområden.
Referenser
- Konfigurera Databas Mail
- Komma igång med Amazon SES
- Länkade servrar
- Säkerhetskopieringshistorik och rubrikinformation