Chapter 14 · Asynchronous Replication, GTIDs, Parallel Apply, and Topology Design

MariaDB GTIDs, Domains, Positions, Strict Mode, and Failover Semantics

Understand MariaDB GTID domain-server-sequence identities, compare binlog/slave/current positions, enforce strict history discipline, and reason safely about repointing and failover.

Advanced140–175 minutesGTID state + divergence labMariaDB Community 12.3.2 baselineCurriculum anchor: 11.8 LTS · verify target versionLast reviewed: August 2026

Learning outcomes

File names such as mariadb-bin.000018:492731 are physical coordinates. They work, but failover becomes easier to reason about when transactions have logical identities that remain stable across servers. MariaDB's Global Transaction ID (GTID) is a three-number tuple domain_id-server_id-sequence_number, for example 14-141-203.

A domain is an ordered transaction stream. The server ID records where the event group was first logged, and the sequence number increases within the stream. MariaDB's GTID model is not MySQL's UUID-based SID model; never copy failover instructions across vendors without translating semantics and testing exact versions.

01

Decode MariaDB GTID domain-server-sequence triplets and explain why domains are topology design, not decoration.

02

Distinguish gtid_binlog_pos, gtid_slave_pos, and gtid_current_pos using observable server state.

03

Use MASTER_USE_GTID=slave_pos deliberately and explain current_pos hazards when local transactions exist.

04

Use gtid_strict_mode as a guardrail and diagnose divergent local history.

05

Explain how GTID positions simplify repointing while still requiring fencing and data-loss checks.

1. Three GTID positions answer three different questions

Variable Mental model Operational question
gtid_binlog_pos GTIDs represented in this server's own binary log What history has this server itself logged?
gtid_slave_pos GTIDs applied by replication from upstream How far has replication replay advanced?
gtid_current_pos combined current position derived from local-binlog and replicated state What GTID state does this server currently represent overall?

The distinction matters on a replica that also executes local binlogged transactions. gtid_current_pos can then advance for reasons unrelated to upstream replay. MariaDB's current CHANGE MASTER TO documentation explicitly warns that MASTER_USE_GTID=current_pos can be unsafe during role transitions if local transactions contaminated that position; slave_pos keeps the replication resume point tied to replicated history.

2. Independent GTID lab

yaml · compose.yaml
services:  primary:    image: mariadb:12.3.2    container_name: mdb14-primary    environment:      MARIADB_ROOT_PASSWORD: labroot    command:      - --server-id=141      - --log-bin=mariadb-bin      - --binlog-format=ROW      - --gtid-domain-id=14      - --gtid-strict-mode=ON    ports:      - "33141:3306"  replica:    image: mariadb:12.3.2    container_name: mdb14-replica    environment:      MARIADB_ROOT_PASSWORD: labroot    command:      - --server-id=142      - --log-bin=replica-bin      - --log-slave-updates=ON      - --relay-log=relay-bin      - --gtid-domain-id=14      - --gtid-strict-mode=ON      - --read-only=ON    ports:      - "33142:3306"
shell · start fresh
docker compose down -vdocker compose up -d
sql · primary — reset only this disposable stream
CREATE USER IF NOT EXISTS 'repl'@'%' IDENTIFIED BY 'lab-repl';GRANT REPLICATION REPLICA ON *.* TO 'repl'@'%';-- Disposable lab only: discard initialization-era binlogs before application data.RESET MASTER;SHOW MASTER STATUS;SELECT @@server_id, @@gtid_domain_id, @@global.gtid_binlog_pos;
sql · replica — start from applied GTID state
STOP REPLICA;RESET REPLICA ALL;SET GLOBAL gtid_slave_pos='';CHANGE MASTER TO  MASTER_HOST='primary',  MASTER_PORT=3306,  MASTER_USER='repl',  MASTER_PASSWORD='lab-repl',  MASTER_USE_GTID=slave_pos;START REPLICA;SHOW REPLICA STATUS\G
sql · primary — generate a known GTID stream
CREATE DATABASE IF NOT EXISTS servicehub_replication_lab;CREATE TABLE IF NOT EXISTS servicehub_replication_lab.tickets (  ticket_id BIGINT PRIMARY KEY,  customer_id BIGINT NOT NULL,  state VARCHAR(20) NOT NULL,  updated_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6)             ON UPDATE CURRENT_TIMESTAMP(6)) ENGINE=InnoDB;INSERT INTO servicehub_replication_lab.tickets(ticket_id,customer_id,state)VALUES (1,101,'open'),(2,102,'open')ON DUPLICATE KEY UPDATE state=VALUES(state);UPDATE servicehub_replication_lab.tickets SET state='assigned' WHERE ticket_id=1;SELECT @@global.gtid_binlog_pos;
sql · replica — compare all positions
SELECT @@global.gtid_binlog_pos AS local_binlog,       @@global.gtid_slave_pos AS replicated,       @@global.gtid_current_pos AS current_state;SHOW REPLICA STATUS\G
Expected pattern

The replica's gtid_slave_pos should include the primary's latest domain-14 sequence after catch-up. If log_slave_updates=ON, replicated events may also be written to the replica's binlog, but the conceptual meaning of the variables remains distinct.

3. Domain IDs create independently ordered streams

If every writer in a traditional single-primary hierarchy uses domain 14, that domain describes one logical write stream. Multi-source or deliberately multi-primary designs may use distinct domains so independent streams can be ordered and, in some cases, applied independently. Reusing a domain for two independently writable primaries is not a harmless naming choice: both can generate sequence histories that collide or diverge.

Design Domain approach Reasoning
single writer + replicas one controlled domain simplest linear history
multi-source independent datasets distinct domains per source stream positions can represent independent ordered streams
two active writers touching same data GTID domains alone do not solve conflicts application/data conflict control still required

Do not assign random domains per server merely because the field exists. Document ownership and expected writers for every active domain.

4. GTID strict mode: fail loudly on impossible history

gtid_strict_mode=ON adds safety checks for sequence histories that would otherwise permit confusing divergence. It is not required for MariaDB GTID replication to function, but it makes automated topologies easier to reason about by stopping on out-of-order or missing-history conditions.

Deliberately wrong approach: binlogged local write on the replica

The replica's read_only setting is an application guardrail, not a magical immutability boundary for privileged administrators. In the disposable lab, temporarily disable it and create a local binlogged transaction in the same GTID domain. This demonstrates why “just fix the replica directly” can contaminate failover state.

sql · replica — create deliberate divergence in the disposable lab
SET GLOBAL read_only=OFF;INSERT INTO servicehub_replication_lab.tickets(ticket_id,customer_id,state)VALUES (900,900,'local-only');SET GLOBAL read_only=ON;SELECT @@global.gtid_binlog_pos, @@global.gtid_slave_pos, @@global.gtid_current_pos;
sql · primary — advance the authoritative stream
INSERT INTO servicehub_replication_lab.tickets(ticket_id,customer_id,state)VALUES (901,901,'primary');
sql · replica — look for a strict-mode stop or conflicting position
SHOW REPLICA STATUS\GSELECT @@global.gtid_binlog_pos, @@global.gtid_slave_pos, @@global.gtid_current_pos;

The exact error text and timing can vary by release and prior GTID state, so diagnose the fields rather than memorizing a string. The important evidence is that local binlogged history changed the replica's logical position. In production, do not paper over this by disabling strict mode until green. Determine whether the local event belongs in authoritative history.

5. Safe repair for the lesson: rebuild, do not rewrite history casually

Because this lab intentionally corrupted role discipline, the clean repair is to destroy and reseed the replica. That mirrors the conservative production principle: when authoritative history is uncertain, a validated rebuild from Chapter 13 is often safer than hand-editing GTID state.

shell · reset the entire disposable lab after the divergence exercise
docker compose down -vdocker compose up -d

In a real topology you would normally rebuild only the affected replica from a trusted primary/backup; the full reset here keeps the lesson self-contained. For real incidents, capture SHOW REPLICA STATUS, GTID variables, binlog inventory, data checks, and application routing before changing anything. If you must reset gtid_slave_pos, treat it as a recovery operation with a documented source of truth and rollback path.

6. Repointing: GTID removes filename coupling, not failover work

Once a replica uses MariaDB GTIDs, it can be pointed to another server that contains the required GTID history without manually translating binlog file/position pairs. The replica requests the next GTID after its saved position. That reduces one class of failover error.

sql · replica — conceptual repointing pattern
STOP REPLICA;CHANGE MASTER TO  MASTER_HOST='candidate-primary',  MASTER_PORT=3306,  MASTER_USER='repl',  MASTER_PASSWORD='rotated-secret',  MASTER_USE_GTID=slave_pos;START REPLICA;SHOW REPLICA STATUS\G

Repointing still fails if the candidate primary purged required binlogs, lacks a domain/sequence the replica needs, has divergent history, or should not be trusted as authoritative. GTID is an identity/position mechanism, not quorum or fencing.

7. MariaDB versus MySQL GTID semantics

Dimension MariaDB MySQL family concept
identifier form domain-server-sequence server UUID/SID plus transaction number
domain concept explicit ordered stream dimension not the same model
resume option MASTER_USE_GTID=slave_pos/current_pos different auto-position syntax/metadata
cross-vendor copy/paste unsafe without exact source/target compatibility testing

8. Production judgment

  • Prefer slave_pos for ordinary replica resume semantics when you want the position to mean “last upstream GTID applied.”
  • Use strict mode as a guardrail only after understanding legacy/local-write behavior and validating your topology.
  • Keep application/DBA writes off replicas unless they are explicitly part of the topology design; read_only plus privilege design from Chapter 12 helps.
  • Document every domain's intended writer(s). A GTID domain is a concurrency/topology boundary, not a label.
  • Before failover, compare executed GTID state and prove the candidate has all required committed transactions; after failover, fence the old primary before accepting writes.

Next, use MariaDB's worker pool and commit-order metadata to accelerate apply without assuming that “more threads” means “less lag.”

Check your understanding

  1. What are the three components of a MariaDB GTID?
  2. Why can gtid_current_pos differ from gtid_slave_pos on a replica?
  3. What does gtid_strict_mode protect against?
  4. Why is a GTID domain a topology decision?
  5. Does GTID-based repointing remove the need to fence the old primary?
Review the answers

A MariaDB GTID is domain ID, server ID, and sequence number. gtid_current_pos can include local binlogged transactions in addition to replicated history, while gtid_slave_pos tracks applied upstream GTIDs. Strict mode adds checks that stop on unsafe/out-of-order history. Domains define independently ordered streams and therefore affect multi-source/multi-writer semantics. GTIDs simplify position tracking but do not provide fencing, consensus, routing, or zero-data-loss guarantees.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.