Promoting a healthy replica to primary keeps write traffic available during a primary failure or a planned switchover. The decisive part is not the role change itself but making one server the only writable authority before applications, proxies, or scheduled jobs resume writes.

Replication replays committed changes from the current primary's binary log onto each replica, so promotion works only if the chosen candidate has applied everything it already fetched and the old primary is fenced. In practice that means stopping new writes, stopping the candidate's I/O thread, letting the SQL thread finish the relay log, then clearing the old replication metadata before the promoted server accepts new transactions.

Command names differ across current products. MySQL 8.0+ uses SHOW REPLICA STATUS, STOP REPLICA, RESET REPLICA, and CHANGE REPLICATION SOURCE TO, while MariaDB and older MySQL builds may still expose SLAVE and MASTER syntax and field names. Multi-source or channel-based topologies follow the same sequence, but each replication statement must include the relevant channel or connection name.

Steps to promote a MySQL or MariaDB replica to primary:

  1. Identify the replica that is closest to the current primary and intended to become the new write target.
  2. Freeze application writes and fence the current primary before touching replication.

    Block the writer endpoint at the proxy, load balancer, VIP, or application layer first. SQL read-only mode reduces risk, but it does not replace fencing because privileged sessions can still write.

  3. Enable read-only protection on the current primary if SQL access is still available.
    $ mysql -u root -p -e "SET GLOBAL read_only = ON;"

    MySQL can also use SET GLOBAL super_read_only = ON;. MariaDB relies on read_only plus endpoint fencing, and accounts with READ ONLY ADMIN or older SUPER privilege can still bypass the setting.

  4. Check the candidate replica state.
    $ mysql -u root -p -e "SHOW REPLICA STATUS\G"
    *************************** 1. row ***************************
    Source_Host: 192.0.2.40
    Replica_IO_Running: Yes
    Replica_SQL_Running: Yes
    Seconds_Behind_Source: 0
    Last_IO_Error:
    Last_SQL_Error:
    Replica_SQL_Running_State: Replica has read all relay log; waiting for more updates
    ##### snipped #####

    MariaDB and older MySQL installations commonly use SHOW SLAVE STATUS\G with Master_ and Slave_ field names.

  5. Stop only the replica I/O thread on the candidate so it stops fetching new events from the old primary.
    $ mysql -u root -p -e "STOP REPLICA IO_THREAD;"

    MariaDB and older MySQL use STOP SLAVE IO_THREAD;.

  6. Wait until the SQL thread finishes every relay-log event the candidate already received.
    $ mysql -u root -p -e "SHOW REPLICA STATUS\G"
    *************************** 1. row ***************************
    Replica_IO_Running: No
    Replica_SQL_Running: Yes
    Seconds_Behind_Source: NULL
    Last_SQL_Error:
    Replica_SQL_Running_State: Replica has read all relay log; waiting for more updates
    ##### snipped #####

    Do not promote while the SQL thread is behind or Last_SQL_Error is non-empty. That leaves the new primary missing committed transactions.

  7. Stop replication completely on the candidate.
    $ mysql -u root -p -e "STOP REPLICA;"

    MariaDB and older MySQL use STOP SLAVE;.

  8. Clear the candidate's old source metadata so it cannot reconnect to the former primary after a restart.
    $ mysql -u root -p -e "RESET REPLICA ALL;"

    This removes the saved replication connection details. MariaDB and older MySQL use RESET SLAVE ALL;.

  9. On MySQL 8.0+ candidates that are becoming a fresh non-GTID source, reset the binary logs before new writes begin.
    $ mysql -u root -p -e "RESET BINARY LOGS AND GTIDS;"

    This gives the promoted MySQL server a new binary log sequence, so downstream replicas can start from the fresh source instead of replaying historical relay-applied events. MariaDB does not use this statement.

  10. Disable read-only protection on the promoted server.
    $ mysql -u root -p -e "SET GLOBAL super_read_only = OFF; SET GLOBAL read_only = OFF;"

    On MariaDB, disable only read_only.

  11. Verify the promoted server is writable and still logging changes.
    $ mysql -u root -p -e "SHOW GLOBAL VARIABLES LIKE 'read_only'; SHOW GLOBAL VARIABLES LIKE 'log_bin';"
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | read_only     | OFF   |
    +---------------+-------+
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | log_bin       | ON    |
    +---------------+-------+

    If log_bin is OFF, other replicas cannot follow the promoted server until binary logging is enabled and the server is restarted with the correct configuration.

  12. Record the promoted server's current binary log position if any remaining replica is not using GTID or auto-positioning.
    $ mysql -u root -p -e "SHOW BINARY LOG STATUS;"
    +------------------+----------+--------------+------------------+-------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+------------------+-------------------+
    | mysql-bin.000001 |      158 |              |                  |                   |
    +------------------+----------+--------------+------------------+-------------------+

    MariaDB and older MySQL use SHOW MASTER STATUS\G. After RESET BINARY LOGS AND GTIDS on a promoted MySQL server, downstream replicas can normally start from the new source's first binary log instead of reusing the former primary's coordinates.

  13. Confirm the promoted server has a working replication user for every remaining replica.
    $ mysql -u root -p -e "SHOW GRANTS FOR 'repl'@'%';"
    Grants for repl@%
    GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO `repl`@`%`

    Downstream replicas cannot reconnect until the promoted server has valid credentials for them. If the account was created after the original seed or excluded from a restore, recreate or regrant it before repointing replicas.

  14. Choose the reattachment method for the remaining replicas.

    If the topology already uses GTID or auto-positioning, keep using that method instead of returning to manual log coordinates. Related: How to enable GTID replication in MySQL or MariaDB

  15. Repoint each remaining MySQL replica at the promoted server.
    $ mysql -u root -p -e "STOP REPLICA; CHANGE REPLICATION SOURCE TO SOURCE_HOST='192.0.2.41', SOURCE_PORT=3306, SOURCE_USER='repl', SOURCE_PASSWORD='ReplPass123!', GET_SOURCE_PUBLIC_KEY=1; START REPLICA;"

    MySQL 8.4 defaults to caching_sha2_password, so non-TLS replication commonly needs GET_SOURCE_PUBLIC_KEY=1 or SOURCE_PUBLIC_KEY_PATH. After RESET BINARY LOGS AND GTIDS on the promoted server, MySQL can start from the new source without specifying SOURCE_LOG_FILE and SOURCE_LOG_POS.

  16. Repoint each remaining MariaDB replica at the promoted server.
    $ mysql -u root -p -e "STOP REPLICA; CHANGE MASTER TO MASTER_HOST='192.0.2.41', MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='ReplPass123!', MASTER_LOG_FILE='mariadb-bin.000001', MASTER_LOG_POS=4; START REPLICA;"

    If MariaDB replication is already using MASTER_USE_GTID=slave_pos or replica_pos, keep using GTID rather than switching back to file and position.

  17. Verify each remaining replica now follows the promoted server.
    $ mysql -u root -p -e "SHOW REPLICA STATUS\G"
    *************************** 1. row ***************************
    Source_Host: 192.0.2.41
    Replica_IO_Running: Yes
    Replica_SQL_Running: Yes
    Seconds_Behind_Source: 0
    Last_IO_Error:
    Last_SQL_Error:
    ##### snipped #####

    If the new Source_Host is correct but the I/O thread cannot connect, check the replication user, TLS or public-key options, and firewall rules on the promoted server before retrying.

  18. Move the application write endpoint to the promoted server only after the replica health checks are clean.

    Exactly one writable primary should receive application writes after the cutover.

  19. Rebuild or fully re-seed the former primary before bringing it back as a replica.

    Reintroducing the old primary without rebuilding it from the new authoritative state can re-create split-brain or reapply diverged transactions.