Automatizovaná záloha všech databází na SQL Express

Express edice SQL Serveru 2008 je dostatečně robustní pro běh řady aplikací, přestože je dostupná zdarma. Většímu nasazení mnohdy brání absence SQL Agenta a Maintenance plánů, které u "velkého" SQL serveru zajišťují automatizovanou údržbu a zálohu databází. S trochou šikovnosti lze ale databáze automaticky zálohovat i u Express edice.

Maintenance plány fungují tak, že vám umožní například zazálohovat všechny databáze nebo na nich provést nějaké údržbové úkoly. SQL Server Agent, který se o ně stará, je jakýsi "task scheduler", který žije uvnitř SQL Serveru a stará se o automatické spouštění úloh.

Express edice nic takového nemá a pokud chceme například automaticky zálohovat všechny databáze, je třeba to naskriptovat vlastními silami. Princip fungování je velmi jednoduchý: V první řadě vytvoříme SQL dávku, která při spuštění projede seznam všech databází a pomocí příkazu BACKUP DATABASE je zazálohuje. Ve druhé řadě pak napíšeme dávkový soubor (CMD), ve kterém pomocí utility SQLCMD dříve vytvořený SQL skript spustíme. Aby se nám zálohy na disku nehromadily až do jeho úplného zaplnění, automaticky rovněž smažeme všechny záložní soubory, které jsou starší než definovaný počet dnů. Tento dávkový soubor pak pomocí systémového task scheduleru spustíme například jednou za den.

ExpressBackup.sql

Takhle bude vypadat soubor ExpressBackup.sql, který provede vlastní zálohování:

/******************************************************************************

** ALL DATABASE BACKUP SCRIPT FOR MICROSOFT SQL SERVER EXPRESS EDITION 2008  **

** Copyright (c) Michal A. Valasek, Altairis, 2009                           **

** http://www.aspnet.cz/ | http://www.altairis.cz/ | http://www.rider.cz/    **

** ------------------------------------------------------------------------- **

** When running from command line:                                           **

**  - set BackupFilePath environment variable                                **

**  - see ExpressBackup.cmd for example                                      **

** When running from SQL management studio:                                  **

**  - enable Query -> SQLCMD mode                                            **

**  - uncomment the ":setvar" line below and specify path                    **

******************************************************************************/

 

-- :setvar BackupFilePath "D:\SqlBackup\" -- include trailing backslash!!

 

-- Declare variables used in the script

DECLARE

  @timestamp AS nvarchar(20),

  @current_id AS int,

  @current_name AS nvarchar(max),

  @current_file AS nvarchar(max)

 

-- Create file name timestamp (YYYYMMDD_hhmmss format)

SET @timestamp = CONVERT(nvarchar, GETDATE(), 20)

SET @timestamp = REPLACE(@timestamp, '-', '')

SET @timestamp = REPLACE(@timestamp, ':', '')

SET @timestamp = REPLACE(@timestamp, ' ', '_')

 

-- Get initial database ID

SELECT @current_id = MIN(database_id) FROM sys.databases WHERE name <> 'tempdb'

 

-- Go trough all databases

WHILE @current_id IS NOT NULL BEGIN

  -- Get database name and backup file

  SELECT @current_name = name FROM sys.databases WHERE database_id = @current_id

  SET @current_file = '$(BackupFilePath)' + @current_name + '_' + @timestamp + '.bak'

 

  -- Backup database

  PRINT 'Backing up database ' + @current_name + ' to ' + @current_file

  BACKUP DATABASE @current_name TO  DISK = @current_file WITH NOINIT

  PRINT NULL

 

  -- Get next database

  SELECT @current_id = MIN(database_id) FROM sys.databases WHERE name <> 'tempdb' AND database_id > @current_id

END

Tato dávka postupně zazálohuje všechny databáze do souboru "NázevDB_YYYYMMDD_hhmmss.bak" ve složce určené SQLCMD proměnnou "BackupFilePath". Výše uvedený skript není primárně určen k tou, aby byl spouštěn interaktivně z Management Studia (i když i to je možné, pokud zapneme SQLCMD režim, viz komentář), ale právě ke spuštění pomocí řádkové utility SQLCMD. V takovém případě se konstrukce $(NázevProměnné) ve skriptu zamění za hodnotu systémové proměnné NázevProměnné.

ExpressBackup.cmd

To je myslím hezky vidět v souboru ExpressBackup.cmd, který dělá v podstatě jenom tři věci: nastaví systémovou proměnnou, zavolá výše uvedenou SQL dávku a poté vymaže všechny záložní soubory starší než 7 dnů (posuzuje to podle data poslední změny souboru, ne podle jeho názvu).

@ECHO OFF

 

REM -- Set path to backup databases to - referenced from the SQL script

REM -- This path must include trailing backslash!

SET BackupFilePath=D:\SqlBackup\

 

REM -- Call SQLCMD with parameters needed to connect to SQL Server

SQLCMD -S .\SqlExpress -E -i ExpressBackup.sql

 

REM -- Delete all backup files older than 7 days

ECHO Deleting backups older than 7 days...

FORFILES /P %BackupFilePath% /M *.bak /D -7 /C "CMD /C DEL /Q @FILE"

Tento soubor (zejména cestu k záložním souborům a volání SQLCMD) si můžete upravit dle potřeby.

Poslední krok pak spočívá v tom, že soubor ExpressBackup.cmd zavoláte jednou za den pomocí systémového plánovače úloh.

Ačkoliv je tento návod ušit na míru Express edici, můžete ho v případě nutnosti použít i na vyšší edice. Nicméně obecně to nedoporučuji, SQL Server Agent umí mnohem víc a vyplatí se s ním naučit zacházet.

V režimu "pouze text" nejsou povoleny žádné HTML značky. Odstavce jsou vytvořeny automaticky, webové adresy a e-maily jsou převedeny na odkazy. V režimu "HTML" jsou povoleny následující elementy: a b i cite strong em p br code blockquote ul ol li. Redakce si vyhrazuje právo komentáře mazat.





Tento web podporuje technologii GRAVATAR.




9 komentářů | řadit podle datumu

Díky za tip

28. prosince 2009 Arci ×××.net.upc.cz

My už nějakou dobu používáme http://www.mssqltips.com/tip.asp?tip=148… ale uznávám, že tohle je lepší varianta.

RE: Díky za tip

Reakce na Díky za ti… 28. prosince 2009 Michal Altair Valášek http://www.rider.cz/ ×××.altairis.cz

Tím řešením jsem se velmi volně inspiroval, ale přijde mi strašně komplikované. Takže jsem to napsal celé znovu, snad jenom ta WHILE smyčka tam zůstala - je to docela elegantní řešení.

Rád se také podělím

3. února 2010 Hans ×××.18.broadband16.iol.cz

Zdravím,

kdysi jsme vygoogloval tento script, který mi zatím funguje spolehlivě. Mám k tomu ještě spouštěcí *.bat soubor, kde jsem použil i LZH knihovnu pro kompresi zálohy.

DECLARE @DBName varchar(255)

DECLARE @DATABASES_Fetch int

DECLARE DATABASES_CURSOR CURSOR FOR

select

DATABASE_NAME = db_name(s_mf.database_id)

from

sys.master_files s_mf

where

-- ONLINE

s_mf.state = 0

-- Only look at databases to which we have access

and has_dbaccess(db_name(s_mf.database_id)) = 1

-- Not master, tempdb or model

and db_name(s_mf.database_id) not in ('Master','tempdb','model','msdb')

group by s_mf.database_id

order by 1

OPEN DATABASES_CURSOR

FETCH NEXT FROM DATABASES_CURSOR INTO @DBName

WHILE @@FETCH_STATUS = 0

BEGIN

declare @DBFileName varchar(256)

set @DBFileName = replace(replace(@DBName,':','_'),'\','_') + '.' +'bak'

exec ('BACKUP DATABASE [' + @DBName + '] TO DISK = N''c:\Users\xxx\Documents\BACKUP_fullSQL\Backup_data\BAK\' +

@DBFileName + ''' WITH NOFORMAT, INIT, NAME = N''' +

@DBName + '-Full Database Backup'', SKIP, NOREWIND, NOUNLOAD, STATS = 100')

FETCH NEXT FROM DATABASES_CURSOR INTO @DBName

END

CLOSE DATABASES_CURSOR

DEALLOCATE DATABASES_CURSOR

RE: Rád se také podělím

Reakce na Rád se tak… 3. února 2010 Michal Altair Valášek ×××.altairis.cz

Jo, to je principiálně totožné, jenom pro načítání názvů databází používáte kurzor místo smyčky. Trochu by mi vadilo, že to dělá jenom jednu zálohu a ne víc verzí zpětně, ale záleží na podmínkách.

RE: Rád se také podělím

Reakce na RE: Rád se… 3. února 2010 Hans ×××.18.broadband16.iol.cz

:-) časové razítko jsem tam měl také, ale tato verze je takovou berličkou, abych nemusel odmazávat staré zálohy (*.bak) , starou zálohu tedy přepisuji a časové razítko si dávám k té zkomprimované, kterou vytvářím přes LZH knihovnu.

Ponechání x posledních záloh na "velkém" SQL serveru

3. února 2010 Hans ×××.18.broadband16.iol.cz

Měl byh ještě otázku, nevěděl byste jak nastavit automatické zálohování na "plném" SQL serveru tak, aby ponechávalo posledních 7 záloh? Měl jsem dojem, že se to řídí parametrem a údajem o expiraci (backup set will expire) zálohy v Maintenance plánu zálohování, ale po vyzkoušení jsem zjistil, že tomu tak není. Má s tím někdo zkušenosti?

RE: Ponechání x posledních záloh na &quot;velkém&quot; SQL serveru

Reakce na Ponechání … 3. února 2010 Michal Altair Valášek ×××.altairis.cz

Je na to task v maintenance plánech. Podívejte se sem:

http://www.mstv.cz/it/videos/373/Nastave…

RE: Ponechání x posledních záloh na &amp;quot;velkém&amp;quot; SQL serveru

Reakce na RE: Ponech… 22. února 2010 Hans ×××.18.broadband16.iol.cz

Zdravím, díky za info a link na zajímavá videa. Ale mám s tím zálohováním malinko problém. Task jsem si do plánu přidal, ale nějak nefunguje. Na disku mi stále zůstávají soubory bez odmazání. Když se podívám do logu, tak tam nikde není zmínka o tom, že by např. nemohl smazat soubor zálohy kvůli právům složky. V délce trvání tasku je 00:00:00 a vše se tváří, jako by to proběhlo. :-(

expressmaint

19. února 2010 manasj 94.124.184.×××

Doporučuji řešení pomocí uložené procedury expressmaint http://www.sqldbatips.com/showarticle.as…, kromě záloh umí i jiné údržbové záležitosti (transakční logy, kontrola integrity, index rebuilding, mazání starých souborů, apod.) Používám jej už od MS SQL 2005 Express a jsem s ním naprosto spokojen.