← Start of tutorial

WIUNIX ACADEMY

Install MariaDB primary-replica replication with GTID and TLS

Page 5 of 6. Review the earlier steps and prerequisites before continuing.

YOUR SYSTEM. YOUR STEPS.

Where are you working?

Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.

Ubuntu 24.04 LTSReviewed against official documentation ·

USE YOUR OWN VALUES

Configure this tutorial

Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.

Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.

Set values for my environment3 editable values

Illustrative status excerpt

Sample output only, not a command and not a promise about your server. Real file names, positions, delays and TLS details vary.

EXAMPLE OUTPUT
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Last_IO_Errno: 0
Last_SQL_Errno: 0
Using_Gtid: Slave_Pos
Master_Server_Id: 101
Master_SSL_Allowed: Yes
Master_SSL_Verify_Server_Cert: Yes
Seconds_Behind_Master: 0
23

LET’S BUILD

Release the primary and commit a new row

Primary only. First confirm replica status and the restored seed row. This releases the bootstrap write pause and commits a new row AFTER the snapshot. Save the returned non-secret GTID; the next replica panel waits for this exact position. Keep application routing on the primary.

Bash

Primary

sudo mariadb -e "SET GLOBAL read_only=OFF; INSERT INTO academy_lab.replication_probe VALUES (2,'after-seed'); SELECT @@GLOBAL.gtid_binlog_pos AS target_gtid; SELECT * FROM academy_lab.replication_probe ORDER BY id;"
How do I know it worked?

Primary read_only0; rows1 and2; record the actual target_gtid returned by this commit.

24

LET’S BUILD

Wait for the commit and compare actual data

Inside a new replica SQL session opened with the earlier terminal panel. Replace the GTID placeholder with the exact primary output, not the sample shown in any article. MASTER_GTID_WAIT returns a non-negative value on success, -1 on timeout or NULL on error. Any -1/NULL is a failure: do not proceed based only on a zero lag field. Compare BOTH rows and their text with the primary. This probes the small table; it is not a checksum of every production object.

SQL

Replica SQL

SELECT MASTER_GTID_WAIT('REPLACE_WITH_ACTUAL_TARGET_GTID',30) AS wait_result;
SELECT id,note FROM academy_lab.replication_probe ORDER BY id;
SHOW SLAVE STATUS\G
EXIT;
How do I know it worked?

Wait is non-negative, rows exactly1 consistent-seed /2 after-seed, receiver/applier both Yes with no error.

25

LET’S BUILD

Check restart recovery without changing roles

Optional planned disruption on the replica ONLY after the row checks. Restart briefly interrupts reads and replication; the configured channel normally starts automatically because skip_slave_start is not set. Confirm both threads, retained GTID/data and read_only again. If replication is stopped by an intentional operational policy, diagnose before explicitly starting it; restarting cannot fix missing logs or drift.

Bash

Replica

sudo systemctl restart mariadb
systemctl is-active mariadb
sudo mariadb -e "SHOW SLAVE STATUS\G; SELECT @@read_only,@@GLOBAL.gtid_slave_pos; SELECT * FROM academy_lab.replication_probe ORDER BY id;"
How do I know it worked?

Same two rows and persisted position; read_only1; receiver/applier recover with zero errors.

26

LET’S BUILD

Keep a separate recoverable backup

On the primary after the verification window; no concurrent schema change/nontransactional writes. This backs up the lab schema and its selected OS configuration/TLS with original directory structure, checks hashes and compares the archive to disk. It retains original data and prior backups and aborts on any failure. The archive contains a private service key: keep it encrypted in approved off-host storage. Hash/read-back checks are not a restore test. Before relying on it or retiring anything, restore the SQL into a separate isolated fresh MariaDB instance with matching versions and verify schemas/rows; never import a recovery dump on a live writer. Plan separate account/system-object backups for a real deployment.

Bash

Primary

sudo bash -eu <<'BACKUP'
umask 077
install -d -m 0700 /root/academy-backups
backup=$(mktemp -d /root/academy-backups/mariadb-XXXXXXXX)
mariadb-dump --single-transaction --quick --routines --events --triggers --databases academy_lab > "$backup/academy_lab.sql"
test -s "$backup/academy_lab.sql"
tar -C / -cpf "$backup/config-tls.tar" etc/mysql/mariadb.conf.d/90-academy-replication.cnf etc/mysql/tls
cd "$backup"
sha256sum academy_lab.sql config-tls.tar > SHA256SUMS
sha256sum -c SHA256SUMS
tar -tf config-tls.tar >/dev/null
tar -C / -df config-tls.tar
printf 'Retained backup: %s\n' "$backup"
BACKUP
How do I know it worked?

Dump/archive read-back pass; originals retained. Acceptance still requires an isolated restore rehearsal and protected off-host copy.

27

LET’S BUILD

Make an intentional pause survive restart

For a rollback/pause, stop directing reads to the replica and keep all writes on the healthy primary. Do not promote either server. On the replica open its own configuration and ADD the next setting within the existing mariadb group, leaving read_only ON. This persistent skip is necessary because STOP SLAVE alone does not survive a service restart.

Bash

Replica

sudo nano /etc/mysql/mariadb.conf.d/90-academy-replication.cnf
How do I know it worked?

Replica configuration opened for the single persistent-pause addition.

28

LET’S BUILD

Persistent pause option

File addition only, inside the existing mariadb section on the replica. Do not replace the rest of the file.

INI · /etc/mysql/mariadb.conf.d/90-academy-replication.cnf

File contents; save in named file, not a shell.

skip_slave_start=ON
How do I know it worked?

One skip_slave_start line is saved within the existing mariadb group; read_only remains ON.

Explore all tutorials ↗