Home/Learn/MySQL/Replication (Primary-Replica)

Replication (Primary-Replica)

Advanced
Scaling

Binary log replication streams changes from primary to replicas asynchronously or semi-synchronously; replicas serve read traffic and provide failover capability.

Overview

MySQL replication streams changes from a primary (source) to one or more replicas using the binary log (binlog). The primary writes changes to the binlog; each replica runs an I/O thread that fetches binlog events and writes them to a local relay log, then an SQL thread applies them. This is asynchronous by default: the primary commits without waiting for replica acknowledgement, meaning replicas can lag and lose committed transactions on primary failure. Semi-synchronous replication (using the rpl_semi_sync plugins) waits for at least one replica to acknowledge receipt before the primary responds to the client, dramatically reducing the data-loss window. GTID (Global Transaction Identifiers) mode, introduced in MySQL 5.6, replaces file+offset-based positioning with universally unique transaction IDs, making failover and replica promotion deterministic and safe.

Setting up GTID-based replication

GTID replication is the modern standard. Each transaction gets a unique ID (server_uuid:transaction_number) that replicas use to track exactly which transactions they have applied, eliminating offset confusion.

Conf + SQL — GTID-based primary/replica setup
# Primary my.cnf
[mysqld]
server-id          = 1
log_bin            = /var/log/mysql/mysql-bin.log
binlog_format      = ROW          # recommended: captures row-level changes
gtid_mode          = ON
enforce_gtid_consistency = ON
sync_binlog        = 1            # flush binlog to disk on each commit (durability)
innodb_flush_log_at_trx_commit = 1

# Replica my.cnf
[mysqld]
server-id          = 2
gtid_mode          = ON
enforce_gtid_consistency = ON
relay_log          = /var/log/mysql/relay-bin.log
read_only          = ON           # prevent accidental writes to replica
super_read_only    = ON           # block even SUPER users

-- Configure replica (MySQL 8.0+ syntax)
CHANGE REPLICATION SOURCE TO
    SOURCE_HOST     = '10.0.0.1',
    SOURCE_USER     = 'replication_user',
    SOURCE_PASSWORD = 'secret',
    SOURCE_AUTO_POSITION = 1;   -- use GTID auto-positioning

START REPLICA;
SHOW REPLICA STATUS\G  -- check Seconds_Behind_Source

Semi-synchronous replication and replication lag

Asynchronous replication risks data loss on primary failure. Semi-sync waits for at least one replica to acknowledge before committing to the client. Monitor replication lag with Seconds_Behind_Source.

SQL — semi-sync setup + lag monitoring
-- Enable semi-synchronous replication (primary side)
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
SET GLOBAL rpl_semi_sync_source_enabled = 1;
SET GLOBAL rpl_semi_sync_source_timeout = 1000; -- fallback to async after 1s

-- Replica side
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';
SET GLOBAL rpl_semi_sync_replica_enabled = 1;

-- Monitor replication lag
SHOW REPLICA STATUS\G
-- Seconds_Behind_Source: NULL = not running, 0 = caught up, N = lagging

-- Prometheus metrics for replication lag (mysqld_exporter)
-- mysql_slave_status_seconds_behind_master
-- Alert when lag > 30s:
# - alert: MySQLReplicationLag
#   expr: mysql_slave_status_seconds_behind_master > 30
#   for: 5m

-- Check GTID executed sets to verify sync
SHOW VARIABLES LIKE 'gtid_executed';   -- primary
SHOW VARIABLES LIKE 'gtid_executed';   -- replica (should match when caught up)

Read/write splitting in Spring Boot

Route writes to the primary and reads to replicas using Spring's AbstractRoutingDataSource. A TransactionSynchronizationManager check on readOnly determines which DataSource to use.

Java — AbstractRoutingDataSource for read/write split
@Configuration
public class DataSourceConfig {

    @Bean
    @Primary
    public DataSource routingDataSource(
            @Qualifier("primaryDs") DataSource primary,
            @Qualifier("replicaDs") DataSource replica) {

        return new AbstractRoutingDataSource() {
            @Override
            protected Object determineCurrentLookupKey() {
                // readOnly transactions route to replica
                return TransactionSynchronizationManager.isCurrentTransactionReadOnly()
                        ? "replica" : "primary";
            }

            {  // init block
                setTargetDataSources(Map.of("primary", primary, "replica", replica));
                setDefaultTargetDataSource(primary);
            }
        };
    }
}

// Usage: @Transactional(readOnly=true) → replica
//        @Transactional → primary
@Service
public class ReportService {
    @Transactional(readOnly = true)  // → replica DataSource
    public List<SalesReport> generateMonthlyReport() { ... }

    @Transactional                   // → primary DataSource
    public void createOrder(Order o) { ... }
}

Key Points to Remember

  • 1Asynchronous replication (default) can lose committed transactions on primary failure; use semi-sync for critical data.
  • 2GTID mode makes failover and replica promotion safe and deterministic — prefer it over file+offset positioning.
  • 3Seconds_Behind_Source (Seconds_Behind_Master in older versions) is the primary replication health signal; alert on > 30s.
  • 4Set read_only=ON and super_read_only=ON on replicas to prevent accidental writes that would break replication.
  • 5Read/write splitting requires application routing logic — AbstractRoutingDataSource or ProxySQL at the proxy layer.
  • 6binlog_format=ROW is recommended over STATEMENT for deterministic replication of non-deterministic functions (NOW(), UUID()).

Interview Questions

Sign in to ask Aria
1

What is the difference between asynchronous and semi-synchronous MySQL replication?

MediumAmazon
2

How do GTIDs make replica failover safer than file+offset-based replication?

HardGoogle
3

How would you implement read/write splitting in a Spring Boot application?

MediumNetflix
4

What does Seconds_Behind_Source = NULL mean and how would you diagnose it?

MediumUber
5

A replica is lagging by 5 minutes. What are the possible causes and how do you investigate?

HardMeta

Ask Aria about Replication (Primary-Replica)

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…