1. Compatibility check
| Check | Why |
|---|---|
Storage engines (SELECT engine, count(*) FROM information_schema.tables GROUP BY engine;) | InnoDB only; convert MyISAM tables first |
SUPER privilege use, DEFINER clauses, plugins | No SUPER on Flexible Server; definers must exist; limited plugins |
lower_case_table_names | Set at server creation for 8.0+; must match the app |
| Tables without primary keys | Replication performance; Flexible Server can enforce sql_generate_invisible_primary_key |
| Version | 5.7 sources should move to 8.0/8.4. Do the version jump deliberately (see the 8.0 → 8.4 upgrade post) |
2. Create the target
az mysql flexible-server create -g rg-db -n mysqlflex-shop --version 8.0.21 \
--tier GeneralPurpose --sku-name Standard_D4ds_v4 --storage-size 512 --auto-scale-iops Enabled \
--high-availability ZoneRedundant --vnet vnet-db --subnet snet-mysql
Check az mysql flexible-server list-skus and supported versions for your region. Copy important server parameters (max_connections, innodb_buffer_pool_size is managed, time_zone, sql_mode).
3. Choose the method
| Method | Downtime | Use when |
|---|---|---|
| Azure DMS (online MySQL migration) | Minutes | Supported source/target combination; you want a managed workflow |
| mydumper/myloader + data-in replication | Minutes | Large databases, more control |
| mysqldump | Hours | Small databases, long window |
4. mydumper + data-in replication path
Source prerequisites: log_bin on, binlog_format=ROW, gtid_mode=ON recommended, a replication user, network path from Azure to the source on 3306 (VPN/ExpressRoute).
Initial load with a consistent snapshot:
mydumper -h src-mysql -u dumper -p '***' -B shop -t 8 --trx-consistency-only -o /mnt/dump/shop
myloader -h mysqlflex-shop.mysql.database.azure.com -u azadmin -p '***' -B shop -t 8 -d /mnt/dump/shop
The dump's metadata file records the binlog position / GTID set at the snapshot.
Start replication on Flexible Server (GTID-based):
CALL mysql.az_replication_change_master_with_gtid('src-mysql.example.com', 'repl', '<password>', 3306, '');
CALL mysql.az_replication_start;
SHOW REPLICA STATUS\G
With GTIDs, first set gtid_purged on the target to the GTID set in the dump metadata. Flexible Server provides a stored procedure for this because you have no SUPER. Position-based alternative: mysql.az_replication_change_master with file and position from the metadata. Check the current procedure names in the Azure docs for your version.
5. Validate
- Row counts and checksums on key tables (pt-table-checksum works across replication).
- Users and grants recreated without
SUPER;DEFINERusers exist. - Events, triggers, routines present.
- App tests with TLS (
require_secure_transportis ON by default).
6. Cut-over
- Stop writes on the source (read-only:
SET GLOBAL super_read_only = ON;). - Wait for
Seconds_Behind_Source = 0and matching GTID sets. CALL mysql.az_replication_stop;thenCALL mysql.az_replication_remove_master;.- Switch connection strings; check AUTO_INCREMENT values continue correctly.
- Keep the source read-only for the rollback window.
7. After go-live
- Alerts: CPU, storage %, IOPS, active connections, replication lag on read replicas.
- Backups: retention and geo-redundancy settings; test a point-in-time restore.
- Slow query log to Log Analytics (server parameters
slow_query_log,log_output).
Warning
lower_case_table_namescan't be changed after the server is created on MySQL 8.0+. Match the source (Windows sources often use 1 or 2) or fix table name casing in the app first.
Checklist
- InnoDB only;
SUPER/definers/plugins reviewed - Server created with correct version and
lower_case_table_names - Initial load + data-in replication rehearsed
- Validation and app TLS tested
- Cut-over and rollback window agreed