patternsqlModerate
Distributed Availability Group with Manual Seeding
Viewed 0 times
groupseedingwithmanualdistributedavailability
Problem
I am looking for a step by step walk through of how to setup a distributed availability group with manual seeding. I can get the automatic seeding working but when I try to manually seed I cannot get the secondary database into the AG on the forwarder.
If I add the distributed AG to the secondary before I try to add the database to the regular AG I get the following message:
If I try to add the DB first without joining the Distributed AG on the secondary, I get the following message because it thinks it should be a primary:
I have none of these problems with automatic seeding. Everything just magically works. All of the examples I find online use automatic seeding.
thanks in advance
If I add the distributed AG to the secondary before I try to add the database to the regular AG I get the following message:
Msg 41190, Level 16, State 7, Line 22
Availability group 'MYDB' failed to process add-database command. The local availability replica is not in a state that could process the command. Verify that the availability group is online and that the local availability replica is the primary replica, then retry the command.If I try to add the DB first without joining the Distributed AG on the secondary, I get the following message because it thinks it should be a primary:
Msg 927, Level 14, State 2, Line 22
Database 'MYDB' cannot be opened. It is in the middle of a restore.I have none of these problems with automatic seeding. Everything just magically works. All of the examples I find online use automatic seeding.
thanks in advance
Solution
TL;DR:
It sounds like from the current description and comments that you may have added databases to the AG on the forward before joining the DAG. Instead, join the DAG first and then add the databases in the following order:
Long(er) form answer
Assuming lots of things like...
... you can... The following scripts are in
Step 0. Disable log backups on
You can ignore this step if:
Step 1. Create the DAG
On the current
On the prospective
Step 2. Full Backups
Did you know you can append log backups to
Step 3. Restore
Once again, executing as an appropriate service account.
Step 3(b). Did you leave the log backups on?
Nbd, but append them now ¯\_(ツ)_/¯
Step 4. On the Forwarder, join DBs to new AG
It sounds like from the current description and comments that you may have added databases to the AG on the forward before joining the DAG. Instead, join the DAG first and then add the databases in the following order:
- Create AG1
- Add Databases to AG1
- Create AG2 (no databases)
- Create the DAG
- Join AGs 1 & 2 to the DAG from AG1
- Join AGs 1 & 2 to the DAG from AG2
- Add databases to AG2
- Profit?
Long(er) form answer
Assuming lots of things like...
- Listeners/Cluster/Instances are already configured
- There is already an AG...
- on both the
PRIMARYand theFORWARDER
- that is not the same AG
- and neither are already a member of another DAG
- and the
FORWARDERAG is empty and ready to seed
- You have shared storage that is accessible from both replicas
... you can... The following scripts are in
sqlcmd format.Step 0. Disable log backups on
|OLD_AG| (optional)You can ignore this step if:
- If you don't mind a potentially "moving target" LSN at the very end of the process or
- You can complete the entire process inside the log backup window of all databases in the AG
Step 1. Create the DAG
CREATE once on the current primary and ALTER ... JOIN on the prospective forwarder. Execute as an appropriate service account so you don't end up with parts of the architecture owned by your user account.On the current
PRIMARY...:connect |OLD_AG|.|DOMAIN|
execute as login = 'sa'
-- double check local replica is manual seeding first
alter availability group [|OLD_AG|]
modify replica on '|THIS_REPLICA|'
with (seeding_mode = manual);
create availability group [|DAG_X|]
with (distributed)
availability group on
'|OLD_AG|' with (
listener_url = 'TCP://|OLD_AG|.|DOMAIN|:|PORT|',
availability_mode = synchronous_commit,
failover_mode = manual,
seeding_mode = manual
),
'|NEW_AG|' with (
listener_url = 'TCP://|NEW_AG|.|DOMAIN|:|PORT|',
availability_mode = synchronous_commit,
failover_mode = manual,
seeding_mode = manual
);
goOn the prospective
FORWARDER...:connect |NEW_AG|.|DOMAIN|
execute as login = 'sa'
alter availability group [|DAG_X|]
join availability group on
'|OLD_AG|' with (
listener_url = 'TCP://|OLD_AG|.|DOMAIN|:|PORT|',
availability_mode = synchronous_commit,
failover_mode = manual,
seeding_mode = manual
),
'|NEW_AG|' with (
listener_url = 'TCP://|NEW_AG|.|DOMAIN|:|PORT|',
availability_mode = synchronous_commit,
failover_mode = manual,
seeding_mode = manual
);
goStep 2. Full Backups
Did you know you can append log backups to
copy_only fulls? Neither did I until very recently! But by using copy_only here you can - protect your backup chain from any migration tomfoolery and
- reduce the length of the restore chain at the end of the process.
exec as... is not strictly necessary for this step. :connect |OLD_AG|.|DOMAIN|
backup database DB1 to disk = N'\\my.shared.storage\backups\DB1.bak'
with copy_only, compression;
backup database DB2 to disk = N'\\my.shared.storage\backups\DB2.bak'
with copy_only, compression;
goStep 3. Restore
Once again, executing as an appropriate service account.
:connect |NEW_AG|.|DOMAIN|
execute as login = 'sa'
restore database DB1 from disk = N'\\my.shared.storage\backups\DB1.bak'
with norecovery;
restore database DB2 from disk = N'\\my.shared.storage\backups\DB2.bak'
with norecovery;
goStep 3(b). Did you leave the log backups on?
Nbd, but append them now ¯\_(ツ)_/¯
- Executing as an appropriate service account
with norecovery
Step 4. On the Forwarder, join DBs to new AG
:connect |NEW_AG|.|DOMAIN|
execute as login = 'sa'
alter database DB1 set hadr availability group = [|NEW_AG|];
alter database DB2 set hadr availability group = [|NEW_AG|];
goCode Snippets
:connect |OLD_AG|.|DOMAIN|
execute as login = 'sa'
-- double check local replica is manual seeding first
alter availability group [|OLD_AG|]
modify replica on '|THIS_REPLICA|'
with (seeding_mode = manual);
create availability group [|DAG_X|]
with (distributed)
availability group on
'|OLD_AG|' with (
listener_url = 'TCP://|OLD_AG|.|DOMAIN|:|PORT|',
availability_mode = synchronous_commit,
failover_mode = manual,
seeding_mode = manual
),
'|NEW_AG|' with (
listener_url = 'TCP://|NEW_AG|.|DOMAIN|:|PORT|',
availability_mode = synchronous_commit,
failover_mode = manual,
seeding_mode = manual
);
go:connect |NEW_AG|.|DOMAIN|
execute as login = 'sa'
alter availability group [|DAG_X|]
join availability group on
'|OLD_AG|' with (
listener_url = 'TCP://|OLD_AG|.|DOMAIN|:|PORT|',
availability_mode = synchronous_commit,
failover_mode = manual,
seeding_mode = manual
),
'|NEW_AG|' with (
listener_url = 'TCP://|NEW_AG|.|DOMAIN|:|PORT|',
availability_mode = synchronous_commit,
failover_mode = manual,
seeding_mode = manual
);
go:connect |OLD_AG|.|DOMAIN|
backup database DB1 to disk = N'\\my.shared.storage\backups\DB1.bak'
with copy_only, compression;
backup database DB2 to disk = N'\\my.shared.storage\backups\DB2.bak'
with copy_only, compression;
go:connect |NEW_AG|.|DOMAIN|
execute as login = 'sa'
restore database DB1 from disk = N'\\my.shared.storage\backups\DB1.bak'
with norecovery;
restore database DB2 from disk = N'\\my.shared.storage\backups\DB2.bak'
with norecovery;
go:connect |NEW_AG|.|DOMAIN|
execute as login = 'sa'
alter database DB1 set hadr availability group = [|NEW_AG|];
alter database DB2 set hadr availability group = [|NEW_AG|];
goContext
StackExchange Database Administrators Q#210297, answer score: 10
Revisions (0)
No revisions yet.