Master-Master MySQL-Replikation mit GTID (Global Transaction ID)

Datum

GTID (Global Transaction ID)?

Der Begriff GTID lässt erahnen, dass jeder Transaktion eine eindeutige ID zugewiesen wird. Der Server, der die Transaktion durchführt, berechnet beim Commit die ID. Sie setzt sich aus zwei Teilen zusammen: der Server UUID und einer fortlaufenden Nummer der Transaktion.

Für ein bestehendes Replikationssetup zwischen Master und Slave(s) gilt ebenfalls, dass GTIDs eindeutig sein müssen. Über das gesamte Master-Slave-Gespann wird eine 1-zu-1-Zuordnung zwischen GTIDs und ausgeführten Transaktionen gepflegt. Diese Information reicht aus, um komplexe Setups zu betreiben, da die MySQL-Server stets wissen, welche Transaktionen auf welchen Servern bereits ausgeführt wurden.

Der GTID-Lebenszyklus im Detail:

1. Der Master führt eine Transaktion durch und wählt die nächste freie GTID aus. Für die Replikation werden beide Teile in das Binary Log geschrieben.

2. Die Binary Logs werden auf Seiten des Slave geholt und ins Relay Log übertragen. Der Slave liest die GTID aus und übernimmt den Wert in die Variable „gtid_next“.

3. Bevor sich der Slave der Transaktion annimmt, prüft er, ob die GTID bereits in seinem eigenen Binary Log vorkommt. Nur wenn das nicht der Fall ist, führt der Slave die Transaktion durch.

4. Der Umweg über die Variable „gtid_ next“ verhindert, dass der Slave eine neue GTID erstellt. Stattdessen korrelieren die Daten zwischen Master und Slave, was das GTID-Transaktions-Paar betrifft.

Quelle: admin-magazin.de

MariaDB-Knowledge Base: https://mariadb.com/kb/en/gtid/

Einrichten der Master-Master Replikation

Vorbereitungen

Ich habe zum einrichten zwei VMs mit jeweils einer frischen Minimal-Installation von Centos8 mit neu installierten Mariadb-Server (Version: 10.3.17).

mysql01: 192.168.2.49
mysql02: 192.168.2.50

Direkt nach der Installation ist der Mariadb/MySQL-Dienst noch nicht gestartet, dies nutzen wir um die folgenden zusätzlichen Parameter in die /etc/my.cnf.d/mariadb-server.cnf in den Abschnitt [mysqld] zu setzen.

auto_increment_increment = 2
auto_increment_offset = 1
gtid_domain_id = 1
gtid_ignore_duplicates = ON
gtid_strict_mode = ON
replicate_ignore_db = mysql
replicate_ignore_db = performance_schema
replicate_ignore_db = information_schema
server_id = 1
binlog_format = mixed
log_bin = /var/lib/mysql/bin-log
log_slave_updates = 1
relay_log = /var/lib/mysql/relay-log

Erläuterungen:

auto_increment_increment und auto_increment_offset werden für eine Master-Master Replikation empfohlen. Weitere Infos dazu: dev.mysql.com

gtid_domain_id wird hierbei, da es sich um eine parallel Replikation handelt benötigt.
Wichtig: diese muss auf den jeweiligen Systemen unterschiedlich sein.

gtid_ignore_duplicates
Wenn diese Option aktiviert ist, können verschiedene Master-Verbindungen in der Replikation mit mehreren Quellen Ereignisgruppen mit derselben GTID empfangen und verarbeiten (bei Verwendung des GTID-Modus).
Es wird nur eine angewendet, alle anderen werden ignoriert. Innerhalb einer bestimmten Replikationsdomäne wird nur die Sequenznummer verwendet, um zu entscheiden, ob eine bestimmte GTID bereits angewendet wurde.
Dies bedeutet, dass es in der Verantwortung des Benutzers liegt, sicherzustellen, dass die GTID-Sequenznummern streng ansteigen. Mit gtid_ignore_duplicates = OFF wird ein doppeltes Ereignis basierend auf der Domänen-ID und der Sequenznummer ausgeführt.
Infos: mariadb.com

gtid_strict_mode
Infos: mariadb.com

replicate_ignore_db
Mit diesem Parameter können bestimmte Datenbanken von der Replikation ausgeschlossen werden.

server_id
Setzt die Server-ID, welche in den binlog Ereignissen protokolliert wird.
Dies wird von mysqlbinlog verwendet, um die Server-ID von GTID-Ereignissen beizubehalten.
WICHITG: Die Server-ID sollten auf den entsprechenden Systemen unterschiedlich sein.

log_bin gibt an unter welchem Pfad die binlogs abgelegt werden sollen.

relay_log gibt an unter welchem Pfad das Relay-Log abgelegt werden soll.

log_slave_updates
Normalerweise protokolliert ein Slave keine Updates, die von einem Master-Server empfangen werden, in seinem eigenen Binärprotokoll. Durch Aktivieren dieser Variablen schreibt der Slave die von seinem SQL-Thread durchgeführten Aktualisierungen in seine einen binlogs.

Nun wird der mariadb Dienst per systemctl restart mariadb.service neu gestartet.

Als letzten wird auf beiden Systemen noch ein entsprechender Replikations-Benutzer eingerichtet. Dies geschieht per:

MariaDB [(none)]> GRANT REPLICATION SLAVE ON *.* TO 'replication'@'192.168.2.%' identified by '123456';
Query OK, 0 rows affected (0.001 sec)

Nun aktualisiert man noch die MySQL-Benutzer:

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.001 sec)

Einrichtung der Replikation

Abfragen der GTID Position

Als erstes richten wir eine einfache Master-Slave Replikation ein.
Hierbei wird nun der mysql01 der Master und der mysql02 der Slave.

Nun fragen wir auf dem ersten zukünftigen Master (mysql01) den aktuellen Master-Status ab um die aktuelle binlog Position zu bekommen.

MariaDB [(none)]> show master status;
+----------------+----------+--------------+------------------+
| File           | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+----------------+----------+--------------+------------------+
| bin-log.000003 |      676 |              |                  |
+----------------+----------+--------------+------------------+
1 row in set (0.000 sec)

Damit bekommen wir die eigentliche GTID Position:

MariaDB [(none)]> select binlog_gtid_pos('bin-log.000003',676);
+---------------------------------------+
| binlog_gtid_pos('bin-log.000003',676) |
+---------------------------------------+
| 1-1-46                                |
+---------------------------------------+
1 row in set (0.001 sec)
Einrichten des Slave mit GTID Position

Auf dem zukünftigen Slave (mysql02) führen wir nun die folgenden Schritte aus:

1.) Anhalten des Slave

MariaDB [(none)]> stop slave;
Query OK, 0 rows affected, 1 warning (0.000 sec)

2.) Reseten des Masters

MariaDB [(none)]> RESET MASTER;
Query OK, 0 rows affected (0.126 sec)

HINWEIS: Dies wird nur bei der initialen Einrichtung auf dem ersten MasterSystem verwendet um einen sauberen Stand zu haben.

3.) Setzen der GTID als aktuelle Slave-Position

MariaDB [(none)]> set global gtid_slave_pos="1-1-46";
Query OK, 0 rows affected (0.042 sec)

4.) Setzen des Masters, des Replikationsbenutzers, etc.
Hierbei sollte man den Eintrag master_use_gtid=slave_pos beachten, welcher dafür sorgt, dass GTIDs verwendet werden.

MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.2.49', MASTER_USER='replication', MASTER_PASSWORD='123456', master_use_gtid=slave_pos;
Query OK, 0 rows affected (0.480 sec)

5.) Starten des Slave

MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.383 sec)

Nun sollte bei einem Aufruf von show slave status\G eine laufende Replikation zu sehen sein:

MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
                Slave_IO_State: Waiting for master to send event
                   Master_Host: 192.168.2.49
                   Master_User: replication
                   Master_Port: 3306
                   Connect_Retry: 60
                   Master_Log_File: bin-log.000003
                   Read_Master_Log_Pos: 676
                   ...
                   Using_Gtid: Slave_Pos
                   Gtid_IO_Pos: 1-1-46
                   ...

Einrichten der Master-Master Replikation

Um nun auch den mysql01 zum weiteren Slave und den mysql02 zum weiteren Master zu machen gehen die Schritte nochmals durch, aber auf den jeweils anderen Systemen.

HINWEIS: Damit der jetzige Slave (mysql02) eine GTID anzeigen kann muss dieser zuvor eine entsprechende Transaktion ausführen, damit diese erstellt wird.
Hierfür reicht eine kurze Erzeugung einer neuen Datenbank:

MariaDB [(none)]> CREATE DATABASE foobar2;
Query OK, 1 row affected (0.002 sec)

Nun fragen wir auf dem zukünftigen neuen Master (mysql02) die aktuelle binlog Position ab um die GTID abzufragen.

MariaDB [(none)]> show master status;
+----------------+----------+--------------+------------------+
| File           | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+----------------+----------+--------------+------------------+
| bin-log.000001 |      882 |              |                  |
+----------------+----------+--------------+------------------+
1 row in set (0.000 sec)

MariaDB [(none)]> select binlog_gtid_pos('bin-log.000001',882);
+---------------------------------------+
| binlog_gtid_pos('bin-log.000001',882) |
+---------------------------------------+
| 1-1-3,2-2-2                           |
+---------------------------------------+
1 row in set (0.001 sec)

Hier sieht man nun, dass bereits eine GTID Domain dazu gekommen ist.

Auf dem neuen zusätzlichen Slave (mysql01) führen wir die folgenden Schritte aus:

1.) Slave stoppen

MariaDB [(none)]> stop slave;
Query OK, 0 rows affected, 1 warning (0.000 sec)

2.) GTID setzen

MariaDB [(none)]> set global gtid_slave_pos="1-1-3,2-2-2";
Query OK, 0 rows affected (0.032 sec)

3.) Setzen der Master Daten

MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.2.50', MASTER_USER='replication', MASTER_PASSWORD='123456', master_use_gtid=slave_pos;
Query OK, 0 rows affected (0.029 sec)

4.) starten des Slaves

MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.016 sec)
MariaDB [(none)]> show slave status\G 
*************************** 1. row***************************
                Slave_IO_State: Waiting for master to send event
                Master_Host: 192.168.2.50
                Master_User: replication
                Master_Port: 3306
                Connect_Retry: 60
                Master_Log_File: bin-log.000001
		        Read_Master_Log_Pos: 882
		        ...
		        Using_Gtid: Slave_Pos
		        Gtid_IO_Pos: 1-1-4,2-2-2
		        ...

Damit ist die Master-Master Replikation fertig.

Autor
Kategorien Datenbanken, Linux

PRTG Map