Migrating AWS Aurora MySQL Cross Accounts

Migrating AWS Aurora MySQL Across Accounts

It turns out there is no straightforward, built-in solution to migrate an Aurora MySQL instance from one AWS account to another. Interestingly, AWS provides cross-region read replicas, so cross-region migration is essentially supported out of the box—but cross-account or even cross-cluster migration within the same region is surprisingly challenging.

In this post, migration refers to near–zero downtime migration for production workloads. Offline migration or downtime-tolerant approaches have many options (snapshots, dump/restore, DMS), but production environments typically require blue-green deployment and continuous replication until cutover. After research and experimentation, MySQL binlog replication proved to be the most practical solution, and it works across regions, clusters, and accounts.


1. Enable Binlog Replication on the Source Cluster

On the source (master/write) Aurora MySQL cluster, update the parameter group:

binlog_format = ROW
binlog_row_image = FULL

Increase binlog retention:

CALL mysql.rds_set_configuration('binlog retention hours', 72);

2. Initial Data Load

Starting replication without an initial data load is impractical for large databases, as the replica would need to process the full binlog history. Instead, preload all data into the target database and capture the binlog file name and position so replication can continue from that point.

You can use either mysqldump or an RDS snapshot.

Option A: Mysqldump

mysqldump \
  --single-transaction \
  --no-tablespaces \
  --skip-lock-tables \
  --source-data=2 \
  --set-gtid-purged=OFF

--source-data=2 embeds the binlog file name and position inside the dump file.

Option B: RDS Snapshot

If you restore from a snapshot, you can find the binlog file name and position in:

  • RDS → Logs & events (Recent events)

Once you have the binlog metadata, you can configure standard MySQL replication.


3. Configure Ongoing Replication

On the Source Database

CREATE USER 'replica_user'@'%' IDENTIFIED BY 'strongRandomPassword';
GRANT REPLICATION CLIENT, REPLICATION SLAVE, SELECT ON *.* TO 'replica_user'@'%';

On the Replica Database

CALL mysql.rds_set_external_source(
    'source-endpoint.ap-southeast-2.rds.amazonaws.com',
    3306,
    'replica_user',
    'strongRandomPassword',
    'mysql-bin-changelog.xxx',
    xxx,
    0
);
CALL mysql.rds_start_replication;

Replace the xxx values with the binlog file name and position captured during the initial load.


4. Cutover

When replication is stable and nearly caught up:

  1. Stop all new writes to the master.
    Aurora cannot make the writer read-only, so you must block writes at the application layer or via security groups.
  2. Stop replication on the replica:
     CALL mysql.rds_stop_replication;
     RESET REPLICA ALL;
  1. Point the application to the new database.

Cutover complete!


5. Cross-Account Networking (VPC Peering)

Binlog replication requires direct network connectivity between the source and target databases. Cross-account VPC peering works the same as same-account peering. AWS documentation covers the full steps, so they’re not repeated here.


Key Takeaways

  • The most challenging part was discovering where to find the binlog file name and position when using RDS snapshots — it appears in RDS events.
  • With mysqldump, --source-data=2 embeds that information directly into the dump file.
  • MySQL binlog replication is a flexible method for cross-account, cross-region, or cross-cluster Aurora MySQL migrations with minimal downtime.

Comments

Popular posts from this blog