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
    Enter password:
    ##### snipped #####
    mysql> SET GLOBAL read_only = ON;
    Query OK, 0 rows affected (0.00 sec)

    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. Connect to the selected replica using mysql.
    $ mysql -u root -p
    Enter password:
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    ##### snipped #####
    mysql>
  6. Check replication status on the selected replica.
    mysql> SHOW SLAVE STATUS\G
    *************************** 1. row ***************************
    Master_Host: db-primary-1.example.net
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    Seconds_Behind_Master: 0
    Relay_Master_Log_File: mysql-bin.001245
    Exec_Master_Log_Pos: 83742193
    Last_IO_Error:
    Last_SQL_Error:
    ##### snipped #####

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

  7. Stop the replication IO thread on the selected replica.
    mysql> STOP SLAVE IO_THREAD;
    Query OK, 0 rows affected (0.00 sec)

    MySQL 8.0+ can use STOP REPLICA IO_THREAD;.

  8. Wait for the SQL thread to apply all remaining relay log events.
    mysql> SHOW SLAVE STATUS\G
    *************************** 1. row ***************************
    Slave_IO_Running: No
    Slave_SQL_Running: Yes
    Seconds_Behind_Master: 0
    Relay_Master_Log_File: mysql-bin.001245
    Exec_Master_Log_Pos: 83742193
    Last_SQL_Error:
    ##### snipped #####

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

  9. Stop replication completely on the selected replica.
    mysql> STOP SLAVE;
    Query OK, 0 rows affected (0.00 sec)

    MySQL 8.0+ can use STOP REPLICA;.

  10. Reset replication metadata on the promoted server when accidental re-attachment to the old primary must be prevented.
    mysql> RESET SLAVE ALL;
    Query OK, 0 rows affected (0.01 sec)

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

  11. Disable read_only on the promoted server.
    mysql> SET GLOBAL read_only = OFF;
    Query OK, 0 rows affected (0.00 sec)

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

  12. Verify the promoted server is writable by checking read_only state.
    mysql> SHOW GLOBAL VARIABLES LIKE 'read_only';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | read_only     | OFF   |
    +---------------+-------+
    1 row in set (0.00 sec)
  13. Verify log_bin is enabled on the promoted server.
    mysql> SHOW GLOBAL VARIABLES LIKE 'log_bin';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | log_bin       | ON    |
    +---------------+-------+
    1 row in set (0.00 sec)

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

  14. Record the promoted server binary log coordinates for replicas that are not using GTID auto-positioning.
    mysql> SHOW MASTER STATUS\G
    *************************** 1. row ***************************
    File: mysql-bin.009812
    Position: 154
    Binlog_Do_DB:
    Binlog_Ignore_DB:
    Executed_Gtid_Set: ##### snipped #####

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

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

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

  16. Stop replication on each remaining replica before changing its upstream.
    mysql> STOP SLAVE;
    Query OK, 0 rows affected (0.00 sec)
  17. Update each remaining replica to replicate from the promoted server using GTID auto-positioning.
    mysql> CHANGE MASTER TO
        MASTER_HOST='db-primary-2.example.net',
        MASTER_PORT=3306,
        MASTER_USER='repl',
        MASTER_PASSWORD='********',
        MASTER_AUTO_POSITION=1;
    Query OK, 0 rows affected (0.02 sec)
    
    mariadb> CHANGE MASTER TO
        MASTER_HOST='db-primary-2.example.net',
        MASTER_PORT=3306,
        MASTER_USER='repl',
        MASTER_PASSWORD='********',
        MASTER_USE_GTID=slave_pos;
    Query OK, 0 rows affected (0.02 sec)

    MySQL 8.0+ can use CHANGE REPLICATION SOURCE TO with SOURCE_AUTO_POSITION=1 instead of CHANGE MASTER TO.

  18. Start replication on each remaining replica.
    mysql> START SLAVE;
    Query OK, 0 rows affected (0.00 sec)

    MySQL 8.0+ can use START REPLICA;.

  19. Verify replication health on each remaining replica after the change.
    mysql> 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 #####
  20. 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.

Discuss the article:

Comment anonymously. Login not required.