You don't have to write a cursor tsql script to check for new database created and schedule it to run for e.g. every minute. Instead use EVENTDATA() function in conjunction with server level trigger.
IF EXISTS (SELECT * FROM sys.server_triggers
WHERE name = 'ddl_trig_database')
DROP TRIGGER ddl_trig_database
ON ALL SERVER;
GO
CREATE TRIGGER ddl_trig_database
ON ALL SERVER
FOR CREATE_DATABASE
AS
PRINT 'Database Created.'
SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)')
GO
DROP TRIGGER ddl_trig_database
ON ALL SERVER;
GO
Since you now have an automated mechanism in place that will fire up when a new database is created, you can use ALTER AVAILABILITY GROUP and ALTER DATABASE - SET HADR
basically you have to just include :
-- Move each database into the Availability Group
-- Change database name and Group as per your environment.
ALTER DATABASE Test1 SET HADR AVAILABILITY GROUP = TestAG
ALTER DATABASE Test2 SET HADR AVAILABILITY GROUP = TestAG
GO
Thinking of this a little bit more, you can be more creative to automate it --
-- create a driver table
create table AlwaysON_Candidates (
DatabaseName sysname
,createdate datetime default getdate()
,IsAlwaysOnMember bit default 0 -- 0 = Not a part of AG
) -- 1 = Is part of AG
go
-- below insert will be governed by the server level trigger
insert into AlwaysON_Candidates (DatabaseName)
values ('Test1')
--- check the values in the driver table
select *
from AlwaysON_Candidates
--- add database to AG
alter database Test1
set HADR AVAILABILITY group = TestAG
-- update the bit in the driver table AlwaysON_Candidates
update AlwaysON_Candidates
set IsAlwaysOnMember = 1
where DatabaseName = 'Test1'
some good references for setting it up using tsql can be found here and here
EDIT: Below script will help you. Obviously you have to Understand it and test it in a test environment.
/************************************************************************************
Author : Kin Shah
Version : 1.0.0 for dba.stackexchange.com
Note: This script does not have ERROR handling and is not tested.
Use at your own risk, It will print out the sql statements, but wont execute it
unless the print statements have been modified to use "exec"
UNDERSTAND the script and then test it on a TEST environment !!!!!!!!
*************************************************************************************/
-- create table
set ansi_nulls on
go
set quoted_identifier on
go
create table AlwaysON_Candidates (
ID int identity(1, 1)
,EventType nvarchar(128) null
,DatabaseName nvarchar(128) null
,LoginName nvarchar(128) null
,UserName nvarchar(128) null
,AuditDateTime datetime null
,IsAlwaysOnMember bit default 0
)
go
alter table [dbo].[AlwaysON_Candidates] add default((0))
for [IsAlwaysOnMember]
go
-- create server trigger
if exists (
select *
from master.sys.server_triggers
where parent_class_desc = 'SERVER'
and name = N'ddl_trig_database'
)
drop trigger [ddl_trig_database] on all server
go
set ansi_nulls on
go
set quoted_identifier on
go
create trigger [ddl_trig_database] on all server
for CREATE_DATABASE as
insert into NewDatabases
select EVENTDATA().value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(128)') as EventType
,EVENTDATA().value('(/EVENT_INSTANCE/DatabaseName)[1]', 'nvarchar(128)') as DatabaseName
,EVENTDATA().value('(/EVENT_INSTANCE/LoginName)[1]', 'nvarchar(128)') as LoginName
,EVENTDATA().value('(/EVENT_INSTANCE/UserName)[1]', 'nvarchar(128)') as UserName
,GETDATE() as AuditDateTime
,0 as IsAlwaysOnMember
go
set ansi_nulls off
go
set quoted_identifier off
go
ENABLE trigger [ddl_trig_database] on all server
go
--- PREREQUISITE ... CREATE A LINKED SERVER FROM PRIMARY TO SECONDARY SERVER !!!
--- fill in *** CHANGE HERE values
--- test it on a TEST server
--- Not tested and not responsible for any dataloss. UNDERSTAND it and test it before implementing it.
declare @databasename varchar(max)
declare @sqlbackup varchar(max)
declare @sqlrestore varchar(max)
declare @PrimaryAG varchar(max)
declare @SecondaryAG varchar(max)
declare @backupPath varchar(max)
set @backupPath = '\\servername\sharedfolder\' --- *** CHANGE HERE
declare @group sysname
set @group = N'your_group_name' --- *** CHANGE HERE
declare @remotesql1 varchar(max)
declare @remotesql2 varchar(max)
declare @linkedserverName sysname
set @linkedserverName = 'kin_test_AG_LS' --- *** CHANGE HERE
select @databasename = min(DatabaseName)
from AlwaysON_Candidates
where IsAlwaysOnMember = 0
while @databasename is not null
begin
-- ** BACKUP HAPPENS HERE **
select @sqlbackup = N'BACKUP DATABASE ' + QUOTENAME(@databasename) + ' TO DISK = ''' + @backupPath + @databasename + '_forAG.BAK'' WITH COPY_ONLY, FORMAT, INIT, COMPRESSION;
BACKUP LOG ' + QUOTENAME(@databasename) + ' TO DISK = ''' + @backupPath + @databasename + '_forAG.TRN'' WITH INIT, COMPRESSION;'
from AlwaysON_Candidates
where IsAlwaysOnMember = 0
print @sqlbackup --- *** CHANGE HERE for EXEC master..sp_executesql @sqltext
-- ** RESTORE HAPPENS HERE **
select @sqlrestore = N'RESTORE DATABASE ' + QUOTENAME(@databasename) + ' FROM DISK = ''' + @backupPath + @databasename + '_forAG.BAK'' WITH REPLACE, NORECOVERY;
RESTORE LOG ''' + @backupPath + @databasename + '_forAG.TRN'' WITH NORECOVERY;'
print @sqlrestore
select @remotesql1 = N'EXEC ' + QUOTENAME(@linkedserverName) + '.master..sp_executesql @sqlrestore;'
print @remotesql1 --- *** CHANGE HERE for EXEC master..sp_executesql @sqltext
-- join the AG group on primary
select @PrimaryAG = N'ALTER AVAILABILITY GROUP ' + QUOTENAME(@group) + ' ADD DATABASE ' + QUOTENAME(@databasename) + ';'
print @PrimaryAG --- *** CHANGE HERE for EXEC master..sp_executesql @sqltext
-- join the AG group on secondary
select @SecondaryAG = 'ALTER DATABASE ' + QUOTENAME(@databasename) + ' SET HADR AVAILABILITY GROUP = ' + QUOTENAME(@group) + ' ;'
print @SecondaryAG
select @remotesql2 = N'EXEC ' + QUOTENAME(@linkedserverName) + '.master..sp_executesql @sqlrestore;'
print @remotesql2 --- *** CHANGE HERE for EXEC master..sp_executesql @SecondaryAG
-- finally update the table
update AlwaysON_Candidates
set IsAlwaysOnMember = 1
where DatabaseName = @databasename
-- go to another database if it is added newly
select @databasename = min(DatabaseName)
from AlwaysON_Candidates
where IsAlwaysOnMember = 0
and DatabaseName > @databasename
end
After poking around in SSMS for a while I noticed that on the secondary replica there was a pause icon next to the Availability Databases. The primary had shown both were "green", but there was an option on the secondary to Resume Data Movement. I resumed the first database, and immediately the In Recovery status message was removed. A minute later it changed from Not Synchronizing to Synchronized, and everything worked as expected.
Here is a screenshot of the AG Databases after I fixed "Patch", but before fixing the test database:
Note you can also use TSQL on the secondary to resume replication on multiple database at the same time:
ALTER DATABASE [Patch] SET HADR RESUME;
ALTER DATABASE [test] SET HADR RESUME;
GO
Best Answer
No, because you can't restore a database that is in an AG. Thus, to restore it'd have to be out of the AG and wouldn't be subject to database level health detection.
Suspended isn't a database state - suspect is, not sure which you meant. Also, the key with this is that it may "attempt" to failover but doesn't mean it will be successful.
It works at the Availability Group level, that's up to you on how and what you put into your AGs. You might have a single app in an AG or you might have multiple. Personally, I would only put the databases that need to be together in the same AG and not co-mingle any other application databases.
If your entire intranet relied on all 50 databases being on the same instance, then yes I'd put them all together... whether or not you want the AG to failover if a single database (might be the most important one or the least important one) has a state change. I can't make that business decision for you. I also can't change the need to have all 50 together.