もちろん、処理するデータベースのリストを含む次のようなスクリプトを使用できます。
-- Houseclean.
set nocount on
if Object_Id( N'tempdb..#DatabasesToProcess' ) is not NULL
drop table #DatabasesToProcess
go
declare @CurrentDateTime as DateTime = SysUTCDateTime()
-- We may wish to change the backup schedule:
-- Full backup daily.
-- Differential backup every two hours. (12 per daily backup.)
-- Transaction log backup every 10 minutes. (12 per differential backup.)
-- At most we should need to restore: most recent full backup, most recent differential backup, up to 12 log backups since the differential backup.
-- If this was a real emergency, we should attempt a tail-log backup to capture the last transactions from the ill database.
-- BACKUP LOG database_name TO backup_filename WITH NORECOVERY
-- NB: The compression option ("compression" or "no_compression") must be a keyword, variables are not supported.
-- Start with the list of databases to be managed and other configuration parameters.
-- IntervalSkew lets us shift the backup cycle for each database so that we are not doing all of the full backups during the same interval.
declare @DatabaseNames as Table ( Name NVarChar(64), IntervalSkew Int )
insert into @DatabaseNames ( Name, IntervalSkew ) values
( N'master', 0 ), ( N'model', 0 ), ( N'msdb', 0 ), ( N'Foo', 1 ), ( N'FooElmah', 2 ), ( N'Bar', 0 )
-- Directory for the backup files.
declare @BackupDirectory as NVarChar(256) = 'C:\SQLServerBackups\'
-- Scheduled interval for this job. We are assuming that we can get the backups done within this time.
-- NB: SQL Server Agent will not start a second instance of this job if the previous instance is still executing.
declare @MinutesPerInterval as Int = 10
-- Number of intervals between differential backups. Two hours: 12 intervals * 10 minutes/interval. Generates 12 differential backups/day.
declare @IntervalsPerDifferentialBackup as Int = 12
-- Number of intervals to shift daily operations from midnight UTC, e.g. 30 * 10 minutes/interval would cause the cycle to start at 05:00 UTC.
declare @IntervalOffset as Int = 30
-- It might be nice if we could use msdb.dbo.sp_help_* to confirm that we are scheduled to run at the correct interval.
-- Determine the backup type(s) for the current interval.
declare @CurrentDateTimeImprint as NVarChar(32) = Replace( Convert( NVarChar(19), @CurrentDateTime, 126 ), ':', '-' ) + 'Z' -- yyyy-mm-ddThh-mm-ssZ
declare @TimeOfDay as Time = @CurrentDateTime
declare @MinuteOfDay as Int = DatePart( hour, @TimeOfDay ) * 60 + DatePart( minute, @TimeOfDay )
declare @Interval as Int = ( @MinuteOfDay / @MinutesPerInterval - @IntervalOffset ) % ( 24 * 60 / @MinutesPerInterval )
print 'Pass started: ' + Convert( VarChar(23), @CurrentDateTime, 126 ) +
', Interval #: ' + Convert( VarChar(4), @Interval ) + ' (Offset ' + Convert( VarChar(4), @IntervalOffset ) + ')'
-- Get the metadata for the databases.
select d.name, d.recovery_model_desc, d.state_desc, drs.last_log_backup_lsn, DNs.IntervalSkew
into #DatabasesToProcess
from @DatabaseNames as DNs inner join
sys.databases as d on d.name = DNs.Name inner join
sys.database_recovery_status as drs on drs.database_id = d.database_id
declare @name as sysname
declare @recovery_model_desc as nvarchar(60)
declare @state_desc as nvarchar(60)
declare @last_log_backup_lsn as numeric(25,0)
declare @IntervalSkew as Int
-- Process the databases.
declare @FullBackup as Bit
declare @DifferentialBackup as Bit
declare @LogBackup as Bit
declare @Database as NVarChar(128)
declare @BackupType as NVarChar(16)
declare @TargetFile as NVarChar(128)
declare DB cursor for
select name, recovery_model_desc, state_desc, last_log_backup_lsn, IntervalSkew
from #DatabasesToProcess
order by name
open DB
fetch next from DB into @name, @recovery_model_desc, @state_desc, @last_log_backup_lsn, @IntervalSkew
while @@Fetch_Status = 0
begin
-- Process the database.
set @Interval = ( @MinuteOfDay / @MinutesPerInterval - @IntervalOffset - @IntervalSkew ) % ( 24 * 60 / @MinutesPerInterval )
set @FullBackup = case when @Interval = 0 then 1 else 0 end
set @DifferentialBackup = case
when @name = N'master' then 0 -- The master database does not support differential backups.
when @Interval > 0 and @Interval % @IntervalsPerDifferentialBackup = 0 then 1
else 0 end
set @LogBackup = case
when @recovery_model_desc = N'SIMPLE' then 0
when @Interval % @IntervalsPerDifferentialBackup != 0 then 1
else 0 end
print '> Database: ' + @name + ', Recovery Model: ' + @recovery_model_desc + ', State: ' + @state_desc +
', Last Log LSN: ' + Coalesce( Convert( VarChar(32), @last_log_backup_lsn ), 'n/a' ) + ', Skew: ' + Convert( VarChar(4), @IntervalSkew ) +
', Adjusted Interval #: ' + Convert( VarChar(4), @Interval ) +
', Full Backup: ' + case when @FullBackup = 1 then 'YES' else 'NO' end +
', Differential Backup: ' + case when @DifferentialBackup = 1 then 'YES' else 'NO' end +
', Log Backup: ' + case when @LogBackup = 1 then 'YES' else 'NO' end
if @FullBackup = 1
begin
set @BackupType = 'FULL'
set @TargetFile = @BackupDirectory + @name + '_' + @CurrentDateTimeImprint + '_' + @BackupType + '.bak'
print '> > Backup Type: ' + @BackupType + ', Target File: ' + @TargetFile + ', Starting: ' + Convert( VarChar(23), SysUTCDateTime(), 126 ) + 'Z'
backup database @name to disk = @TargetFile with init, skip, checksum, compression
end
if @DifferentialBackup = 1
begin
set @BackupType = 'DIFF'
set @TargetFile = @BackupDirectory + @name + '_' + @CurrentDateTimeImprint + '_' + @BackupType + '.bak'
print '> > Backup Type: ' + @BackupType + ', Target File: ' + @TargetFile + ', Starting: ' + Convert( VarChar(23), SysUTCDateTime(), 126 ) + 'Z'
backup database @name to disk = @TargetFile with differential, init, skip, checksum, compression
end
if @LogBackup = 1
begin
set @BackupType = 'TLOG'
set @TargetFile = @BackupDirectory + @name + '_' + @CurrentDateTimeImprint + '_' + @BackupType + '.bak'
print '> > Backup Type: ' + @BackupType + ', Target File: ' + @TargetFile + ', Starting: ' + Convert( VarChar(23), SysUTCDateTime(), 126 ) + 'Z'
begin try
backup log @name to disk = @TargetFile with init, checksum
end try
begin catch
print '> > ERROR: ' + Error_Message() + ' (' + Convert( VarChar(12), Error_Number() ) + ')'
end catch
end
fetch next from DB into @name, @recovery_model_desc, @state_desc, @last_log_backup_lsn, @IntervalSkew
end
close DB
deallocate DB
drop table #DatabasesToProcess
print 'Pass completed: ' + Convert( VarChar(23), SysUTCDateTime(), 126 ) + 'Z'