Promoting a replica to primary keeps services writable during a primary failure or a planned switchover. The operation matters because replication is usually asynchronous, so the most recent commits can live on only one server at a time. Skipping the safety rails can create split-brain, which turns debugging into archaeology.

MySQL and MariaDB replication ships transactions from the primary binary log to replicas. A replica runs an IO thread to fetch events into a local relay log, then an SQL thread applies those events to its data files. Promotion is the controlled moment where replication stops, the candidate becomes writable, and the rest of the topology is repointed at the new authoritative server.

The current primary must be fenced so it cannot accept writes after promotion, even briefly. If the primary is already dead, any transactions not replicated before the outage are unrecoverable without backups or binlog capture from that host. The steps below assume a single-source topology; channel-based replication needs the same actions with channel names added.

Steps to promote a replica to primary:

  1. Identify the replica intended to become the new primary.
  2. Confirm the write endpoint can be updated to point at the selected replica.

    Common write endpoints include a load balancer VIP, a DNS name, or a database proxy.

  3. Stop application write traffic to the current primary.

    Split-brain starts when the old primary accepts writes after promotion, so block write traffic before any replication is stopped.

  4. Enable read_only on the current primary when SQL access is still available.
    $ mysql -u root -p -e "SET GLOBAL read_only = ON;"

    MySQL can still allow privileged writes while read_only is enabled, so set super_read_only when supported: SET GLOBAL super_read_only = ON;.

  5. Check replication status on the selected replica.
    $ mysql -u root -p -e "SHOW SLAVE STATUS\G"
    *************************** 1. row ***************************
    Master_Host: 192.0.2.40
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    Seconds_Behind_Master: 0
    Relay_Master_Log_File: mysql-bin.000002
    Exec_Master_Log_Pos: 2323
    Last_IO_Error:
    Last_SQL_Error:
    ##### snipped #####

    MySQL 8.0+ can use SHOW REPLICA STATUS\\G with fields named Replica_ instead of Slave_.

  6. Stop the replication IO thread on the selected replica.
    $ mysql -u root -p -e "STOP SLAVE IO_THREAD;"

    MySQL 8.0+ can use STOP REPLICA IO_THREAD;.

  7. Wait for the SQL thread to apply all remaining relay log events.
    $ mysql -u root -p -e "SHOW SLAVE STATUS\G"
    *************************** 1. row ***************************
    Slave_IO_Running: No
    Slave_SQL_Running: Yes
    Seconds_Behind_Master: NULL
    Relay_Master_Log_File: mysql-bin.000002
    Exec_Master_Log_Pos: 2323
    Last_SQL_Error:
    ##### snipped #####

    Promotion is safest when Seconds_Behind_Master is 0 and Last_SQL_Error is empty.

  8. Stop replication completely on the selected replica.
    $ mysql -u root -p -e "STOP SLAVE;"

    MySQL 8.0+ can use STOP REPLICA;.

  9. Reset replication metadata on the promoted server when accidental re-attachment to the old primary must be prevented.
    $ mysql -u root -p -e "RESET SLAVE ALL;"

    RESET SLAVE ALL clears replication connection state, so restarting replication later requires a fresh CHANGE MASTER TO configuration.

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

    If super_read_only is enabled, turn it off first: SET GLOBAL super_read_only = OFF;.

  11. Verify the promoted server is writable by checking read_only state.
    $ mysql -u root -p -e "SHOW GLOBAL VARIABLES LIKE 'read_only';"
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | read_only     | OFF   |
    +---------------+-------+
  12. Verify log_bin is enabled on the promoted server.
    $ mysql -u root -p -e "SHOW GLOBAL VARIABLES LIKE 'log_bin';"
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | log_bin       | ON    |
    +---------------+-------+

    When log_bin is OFF, other replicas cannot replicate from the promoted server without a restart and config change.

  13. Record the promoted server binary log coordinates for replicas that are not using GTID auto-positioning.
    $ mysql -u root -p -e "SHOW MASTER STATUS\G"
    *************************** 1. row ***************************
    File: mysql-bin.000003
    Position: 3531802
    Binlog_Do_DB:
    Binlog_Ignore_DB:
    Executed_Gtid_Set:

    GTID-based replication typically repoints replicas with auto-positioning, which avoids manual file/position handling.

  14. Switch the application write endpoint to the promoted server.

    Reads can remain on replicas, but writes must converge on exactly one primary.

  15. Stop replication on each remaining replica before changing its upstream.
    $ mysql -u root -p -e "STOP SLAVE;"
  16. Update each remaining replica to replicate from the promoted server using file and position coordinates.
    $ mysql -u root -p -e "CHANGE MASTER TO MASTER_HOST='192.0.2.41', MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='ReplPass123!', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=3531802;"

    MySQL 8.0+ can use CHANGE REPLICATION SOURCE TO syntax with SOURCE_LOG_FILE and SOURCE_LOG_POS.

  17. Start replication on each remaining replica.
    $ mysql -u root -p -e "START SLAVE;"

    MySQL 8.0+ can use START REPLICA;.

  18. Verify replication health on each remaining replica after the change.
    $ mysql -u root -p -e "SHOW SLAVE STATUS\G"
    *************************** 1. row ***************************
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    Seconds_Behind_Master: 0
    Last_IO_Error:
    Last_SQL_Error:
    ##### snipped #####
  19. Rebuild the former primary as a replica of the promoted server before allowing it back into service.

    Reintroducing the former primary without re-seeding or replication can spread diverged data and re-create split-brain.