Replication monitoring matters because a replica can keep serving reads while quietly falling behind the authoritative server. Catching lag, stopped threads, or repeated reconnects early keeps failover predictable, prevents stale reads from drifting into reports or applications, and narrows the search when the problem is transport, apply, or workload pressure.

Replication health is mostly the state of the receiver and applier threads plus evidence that source and execute positions continue moving. The receiver thread pulls binary log events from the source into relay logs, and the applier thread replays those events locally. A healthy idle replica commonly shows Waiting for source to send event or Waiting for master to send event with both threads running and the read and executed positions aligned.

Current MySQL uses SHOW REPLICA STATUS and returns Replica_* and Source_* fields such as Replica_IO_Running and Seconds_Behind_Source. Current MariaDB also accepts SHOW REPLICA STATUS, but the returned columns still use Slave_* and Master_* names such as Slave_SQL_Running and Seconds_Behind_Master; current MySQL typically requires the REPLICATION CLIENT privilege for a monitoring account, while current MariaDB requires REPLICA MONITOR. Older servers can still require SHOW SLAVE STATUS, and lag fields can be NULL or briefly misleading during stoppages, delayed replication, or large transactions.

Steps to monitor MySQL or MariaDB replication:

  1. Connect to the replica with a monitoring account and run the current status statement in vertical output mode.
    $ mysql --user=monitor --password --execute "SHOW REPLICA STATUS\G"

    Current MySQL monitoring users need REPLICATION CLIENT. Current MariaDB monitoring users need REPLICA MONITOR. A dedicated monitoring account limits blast radius compared with using root.

    If an older server rejects SHOW REPLICA STATUS, retry with SHOW SLAVE STATUS\G.

  2. Confirm the command returns the replica channel intended for the check.

    Empty set or 0 rows usually means replication is not configured on that server, the wrong channel was queried, or the command was run on a primary instead of a replica.

  3. On current MySQL, read the main health fields from the Replica_* and Source_* output.
    *************************** 1. ROW ***************************
              Replica_IO_State: Waiting FOR SOURCE TO send event
                   Source_Host: db01.example.com
                   Source_User: repl
               Source_Log_File: mysql-bin.000003
           Read_Source_Log_Pos: 1604
         Relay_Source_Log_File: mysql-bin.000003
            Replica_IO_Running: Yes
           Replica_SQL_Running: Yes
            Exec_Source_Log_Pos: 1604
         Seconds_Behind_Source: 0
                 Last_IO_Error:
                Last_SQL_Error:
    ##### snipped #####

    MySQL 8.0.22 and later prefer these Replica_* and Source_* field names. Older MySQL releases use SHOW SLAVE STATUS with the legacy Slave_* and Master_* equivalents.

  4. On current MariaDB, read the same health checks from the legacy Slave_* and Master_* columns that still back SHOW REPLICA STATUS.
    *************************** 1. ROW ***************************
                 Slave_IO_State: Waiting FOR master TO send event
                    Master_Host: db01.example.com
                    Master_User: repl
                Master_Log_File: mariadb-bin.000002
            Read_Master_Log_Pos: 1341
          Relay_Master_Log_File: mariadb-bin.000002
               Slave_IO_Running: Yes
              Slave_SQL_Running: Yes
            Exec_Master_Log_Pos: 1341
          Seconds_Behind_Master: 0
                  Last_IO_Error:
                 Last_SQL_Error:
    ##### snipped #####

    Current MariaDB documentation still describes these Slave_* and Master_* columns under SHOW REPLICA STATUS, so the command name is newer than many of the returned field names.

  5. Treat the receiver and applier thread states as the first alarm condition.

    Replica_IO_Running or Slave_IO_Running set to No means the replica is not receiving fresh events. Replica_SQL_Running or Slave_SQL_Running set to No means the replica stopped applying events and Last_SQL_Error usually explains why.

    Waiting for source to send event or Waiting for master to send event is a healthy idle state when both thread flags are Yes and the positions are caught up.

  6. Compare the read position with the executed position to separate transport lag from apply lag.

    On MySQL, compare Read_Source_Log_Pos with Exec_Source_Log_Pos. On MariaDB, compare Read_Master_Log_Pos with Exec_Master_Log_Pos. If the read position advances while the executed position stays flat, the applier is falling behind. If neither moves while writes continue on the source, the receiver side is the likely problem.

  7. Treat the lag field as an estimate rather than a proof of health.

    Seconds_Behind_Source or Seconds_Behind_Master at 0 usually means the replica is caught up at that moment. NULL is common when replication threads are stopped or the lag cannot be calculated, and current MariaDB documents a known case where Seconds_Behind_Master can briefly show 0 after a replica restart until a new replicated transaction begins executing.

  8. Inspect Last_IO_Error and Last_SQL_Error for non-empty messages.

    Last_IO_Error usually points at connectivity, DNS, authentication, TLS, or source-availability problems. Last_SQL_Error usually points at apply failures such as missing rows, duplicate keys, or schema drift.

  9. Re-run the status query after a short interval or after a known write on the source.
    *************************** 1. ROW ***************************
               Source_Log_File: mysql-bin.000003
           Read_Source_Log_Pos: 1893
         Relay_Source_Log_File: mysql-bin.000003
            Replica_IO_Running: Yes
           Replica_SQL_Running: Yes
            Exec_Source_Log_Pos: 1893
         Seconds_Behind_Source: 0
                 Last_IO_Error:
                Last_SQL_Error:
    ##### snipped #####

    Unchanged positions together with continuing source writes indicate a stall even when the lag field still looks harmless.

  10. Save a point-in-time status snapshot for incident notes or handoff.
    $ mysql --user=monitor --password --execute "SHOW REPLICA STATUS\G" > replication-status.txt

    Avoid putting the password value directly on the command line because it can leak through shell history or process listings.

  11. Check each named channel separately on multi-source replicas.
    $ mysql --user=monitor --password --execute "SHOW REPLICA STATUS FOR CHANNEL 'analytics'\G"

    Current MariaDB also supports FOR CHANNEL for MySQL compatibility and can list every connection with SHOW ALL REPLICAS STATUS.

  12. Poll a reduced field set and alert when thread state, lag, or error fields change.
    $ mysql --user=monitor --password --execute "SHOW REPLICA STATUS\G" | egrep 'Replica_IO_Running|Replica_SQL_Running|Seconds_Behind_Source|Last_IO_Error|Last_SQL_Error'

    On MariaDB, monitor the equivalent Slave_IO_Running, Slave_SQL_Running, and Seconds_Behind_Master fields. Alerting on thread state plus non-empty error text catches most replication failures faster than watching lag alone.