MariaDB Master-Slave Replication on Linux: Production Setup Guide
Database

MariaDB Master-Slave Replication on Linux: Production Setup Guide

  • Author :Liam K.
  • Date :July 01, 2026
  • Time :29 minutes

MariaDB replication copies data from a primary (master) server to one or more replica (slave) servers in near real time. It is the foundation for read scaling, geographic distribution, backups without locking the primary, and disaster recovery preparation. This guide configures GTID-based asynchronous replication — the modern standard that simplifies failover and eliminates the need to track binary log file positions manually.

Replication is not automatic failover. If the primary fails, a replica does not promote itself unless you configure orchestration (MariaDB MaxScale, Orchestrator, or manual procedure). Treat this guide as the replication layer — add failover tooling separately once replication is stable and monitored.

Replication Topology

  • Primary (master) — accepts all writes, records changes in the binary log.
  • Replica (slave) — pulls binlog events via replication thread, applies them locally.
  • GTID — global transaction IDs make position tracking automatic across failovers.
  • Semi-sync (optional) — waits for at least one replica to acknowledge before commit.

Prerequisites

  • Two Linux servers: primary (10.0.0.10) and replica (10.0.0.20)
  • MariaDB 10.6+ or 11.x installed on both servers
  • Identical MariaDB major version on primary and replica
  • Private network connectivity between servers on port 3306
  • Existing database with data on the primary (or fresh install for greenfield)

Step 1: Configure the Primary Server

Enable binary logging and GTID on the primary. Assign a unique server-id. Use ROW binlog format for reliable replication with all storage engines.

bash
sudo tee /etc/mysql/mariadb.conf.d/99-replication.cnf >/dev/null <<'EOF'
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_format = ROW
binlog_expire_logs_seconds = 604800
max_binlog_size = 256M
gtid_strict_mode = ON
[...]
Command truncated. Copy to view full command.

Step 2: Create Replication User

bash
sudo mysql <<'SQL'
CREATE USER 'repl'@'10.0.0.20' IDENTIFIED BY 'REPLACE_WITH_STRONG_PASSWORD';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'10.0.0.20';
FLUSH PRIVILEGES;
SQL

Step 3: Take a Consistent Backup for Initial Sync

The replica needs a point-in-time snapshot that matches the primary's binlog position (or GTID). Use mariadb-backup for hot backups on InnoDB tables without stopping writes.

bash
sudo mariadb-backup --backup \
  --target-dir=/backup/full \
  --user=root \
  --parallel=4

sudo mariadb-backup --prepare --target-dir=/backup/full

# Copy to replica:
rsync -avz /backup/full/ root@10.0.0.20:/backup/full/

Step 4: Configure the Replica Server

bash
sudo tee /etc/mysql/mariadb.conf.d/99-replication.cnf >/dev/null <<'EOF'
[mysqld]
server-id = 2
log_bin = /var/log/mysql/mysql-bin.log
binlog_format = ROW
relay_log = /var/log/mysql/relay-bin
read_only = ON
super_read_only = ON
[...]
Command truncated. Copy to view full command.

Step 5: Restore Backup and Start Replication

bash
# On replica — restore the backup:
sudo systemctl stop mariadb
sudo rm -rf /var/lib/mysql/*
sudo mariadb-backup --copy-back --target-dir=/backup/full
sudo chown -R mysql:mysql /var/lib/mysql
sudo systemctl start mariadb
# Start replication with GTID:
sudo mysql <<'SQL'
[...]
Command truncated. Copy to view full command.

Step 6: Verify Replication Health

bash
sudo mysql -e "SHOW SLAVE STATUS\G" | grep -E 'Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master|Last_Error'

# Both should show:
# Slave_IO_Running: Yes
# Slave_SQL_Running: Yes
# Seconds_Behind_Master: 0 (or low single digits)

Step 7: Route Read Queries to the Replica

Application-level read/write splitting is the simplest approach. Send SELECT queries to the replica connection and INSERT/UPDATE/DELETE to the primary. ORMs like Laravel, Django, and Sequelize support multiple database connections for this pattern.

php
# Laravel config/database.php example:
'mysql' => [
    'read' => [
        'host' => ['10.0.0.20'],
    ],
    'write' => [
        'host' => ['10.0.0.10'],
    ],
[...]
Command truncated. Copy to view full command.

Step 8: Monitor Replication Lag

Replication lag means the replica is behind the primary. Under load, a few seconds is normal. Sustained lag above 30 seconds indicates network issues, slow replica disk, or heavy write volume the replica cannot keep up with.

bash
# Check lag from primary:
sudo mysql -e "SHOW SLAVE HOSTS;"

# On replica:
sudo mysql -e "SELECT TIMESTAMPDIFF(SECOND, ts, NOW()) AS lag_seconds FROM (SELECT MAX(ts) AS ts FROM mysql.gtid_slave_pos) t;"

# Alert if Seconds_Behind_Master > 30 for more than 5 minutes

Step 9: Manual Failover Procedure (Document Before You Need It)

When the primary is unrecoverable, promote the replica. This is a manual process without orchestration — practice it in staging first.

bash
# On replica (after confirming primary is dead):
sudo mysql <<'SQL'
STOP SLAVE;
RESET SLAVE ALL;
SET GLOBAL read_only = OFF;
SET GLOBAL super_read_only = OFF;
SQL
# Update application connection strings to point to 10.0.0.20
[...]
Command truncated. Copy to view full command.

Common Replication Errors

  • Error 1236 — binlog position mismatch. Re-sync with a fresh backup and GTID.
  • Error 1062 — duplicate key on replica. Data divergence — investigate before skipping events.
  • High lag — replica disk too slow, long-running queries on replica, or network latency.
  • GTID conflicts — never restore a random backup onto a replica with active GTID history.

Production Checklist

  • Keep MariaDB versions identical on primary and replica.
  • Restrict replication user to the replica IP only.
  • Monitor Seconds_Behind_Master with alerts above 30 seconds.
  • Run monthly failover drills in staging.
  • Never write to the replica — read_only=ON prevents accidents.
  • Retain binlogs for at least 7 days for point-in-time recovery.

"Replication gives you a copy of your data in real time — but only a tested failover runbook turns that copy into actual recovery capability."

Technical Author

Technical Author - Liam K.
Liam K.

System administrator and technical writer specializing in server infrastructure, security and deployment. Creating comprehensive guides to help you master server administration.