I'm pretty sure what I'm wanting with my current implementation is impossible, the sys.databases catalog view which is scoped at the service level to be aware of other SQL Server instances (lol). But I've thought a lot of things were impossible with computers so hopefully I can solve my problem in a different way.
I've already created a PowerShell solution that uses SMO to backup all databases on all instances, but due to security reasons I'm unable to have that solution work without making the account for the proxy that runs the Agent job a local administrator on the server.
As an alternative I wrote a T-SQL script that will be ran as an Agent job and take either full, differential, or transaction backups on all databases in a SQL Server instance every 15 minutes.
DECLARE @sql nvarchar(MAX) = N'';
--Check time for full backup
IF (DATENAME(weekday,getdate()) = 'Sunday' AND convert(time,getdate()) > '00:00' and convert(time,getdate()) < '00:15')
BEGIN
SELECT @sql += 'BACKUP DATABASE ' + QUOTENAME(name)
+ ' TO DISK = N''C:\backups\' + @@ServiceName + '_' + name + '__'
+ cast(year(getdate()) as nvarchar(4)) + '_' + cast(month(getdate()) as nvarchar(2)) + '_' + cast(day(getdate()) as nvarchar(2)) + '__'
+ cast(datepart(hour,getdate()) as nvarchar(2)) + '_' + cast(datepart(minute,getdate()) as nvarchar(2)) + '_' + cast(datepart(second,getdate()) as nvarchar(3)) + '.bak'''
+ ' WITH COMPRESSION
'
FROM sys.databases
WHERE name <> 'TempDB';
END
--Check time for differential backup
ELSE IF (convert(time,getdate()) > '00:00' and convert(time,getdate()) < '00:15')
BEGIN
SELECT @sql += 'BACKUP DATABASE ' + QUOTENAME(name)
+ ' TO DISK = N''C:\backups\' + @@ServiceName + '_' + name + '__'
+ cast(year(getdate()) as nvarchar(4)) + '_' + cast(month(getdate()) as nvarchar(2)) + '_' + cast(day(getdate()) as nvarchar(2)) + '__'
+ cast(datepart(hour,getdate()) as nvarchar(2)) + '_' + cast(datepart(minute,getdate()) as nvarchar(2)) + '_' + cast(datepart(second,getdate()) as nvarchar(3)) + '.diff'''
+ ' WITH COMPRESSION, Differential
'
FROM sys.databases
WHERE name <> 'TempDB' and name <> 'Master';
END
--Take transaction log backup
ELSE
BEGIN
SELECT @sql += 'BACKUP LOG ' + QUOTENAME(name)
+ ' TO DISK = N''C:\backups\' + @@ServiceName + '_' + name + '__'
+ cast(year(getdate()) as nvarchar(4)) + '_' + cast(month(getdate()) as nvarchar(2)) + '_' + cast(day(getdate()) as nvarchar(2)) + '__'
+ cast(datepart(hour,getdate()) as nvarchar(2)) + '_' + cast(datepart(minute,getdate()) as nvarchar(2)) + '_' + cast(datepart(second,getdate()) as nvarchar(3)) + '.trn'''
+ ' WITH COMPRESSION
'
FROM sys.databases
WHERE name <> 'TempDB' and name <> 'Master';
END
print @sql;
exec sp_Executesql @sql;
This script works fine, however it only backs up ALL databases on ONE instance. The goal is to backup ALL databases on ALL instances. An even better solution is to backup all databases, on all instances, and on all servers. From my current knowledge it seems like there are three solutions, (hopefully more based on answers)
- Use this script in an Agent job on every instance. This will work but just seems like such an ugly solution.
- Figure out how to give the Agent proxy the minimum amount of permissions to successfully run the PowerShell script which is instance aware
- Look into creating a master server. I'm not familiar with this option but I know the master server is aware of other servers, and i may be able to get a list of all databases on all servers.