Version 1.0
Author: Oliver Meyer <o [dot] meyer [at] projektfarm [dot] de>


Diese Anleitung veranschaulicht, wie man eine Master-Master Replication mit MySQL 5 auf Fedora 8 einrichtet. Das daraus resultierende System liefert einen stabilen MySQL Server mit Ausfallsicherung.

Diese Anleitung ist ein praktischer Leitfaden ohne jegliche Garantie - theoretisches Hintergrundwissen wird nicht abgedeckt. Es gibt viele Möglichkeiten ein solches System einzurichten - dies ist der Weg, den ich gewählt habe.

1 Vorbereitung

Für diese Anleitung richte ich zwei Fedora 8 Systeme (minimale Installation ohne gui etc.) mit folgender Konfiguration ein.

1.1 System 1

Hostname: server1.example.com
IP: 192.168.0.100

1.2 System 2

Hostname: server2.example.com
IP: 192.168.0.200

2 MySQL

2.1 Benötigte Pakete auf beiden Systemen

Falls Du MySQL auf beiden Systemen noch nicht installiert hast, kannst Du es nun installieren (Client & Server) via:

yum -y install mysql mysql-server


2.2 MySQL Server - Erster Start auf beiden Systemen

Starte den MySQL Server.

/etc/init.d/mysqld start


2.3 MySQL Root Passwort

2.3.1 Beide Systeme

Richte für den MySQL Rootbenutzer auf localhost ein Passwort ein.

mysqladmin -u root password %sql_root_password%


2.3.2 System 1

Richte ein Passwort für den MySQL Rootbenutzer auf server1.example.com ein.

mysqladmin -u root -h server1.example.com password %mysql_root_password%


2.3.3 System 2

Richte ein Passwort für den MySQL Rootbenutzer auf server2.example.com ein.

mysqladmin -u root -h server2.example.com password %mysql_root_password%


2.4 MySQL Replication Benutzer

2.4.1 System 1

Erstelle den Replication Benutzer, den System 2 verwenden wird, um auf die MySQL Datenbank auf System 1 zugreifen zu können.

mysql -u root -p


GRANT REPLICATION SLAVE ON *.* TO 'slave2_user'@'%' IDENTIFIED BY '%mysql_slaveuser_password%';
FLUSH PRIVILEGES;
quit;

2.4.2 System 2

Erstelle den Replication Benutzer, den System 1 verwenden wird, um auf die MySQL Datenbank auf System 2 zugreifen zu können.

mysql -u root -p


GRANT REPLICATION SLAVE ON *.* TO 'slave1_user'@'%' IDENTIFIED BY '%mysql_slaveuser_password%';
FLUSH PRIVILEGES;
quit;

2.5 Datenbank auf System 2

Ich nehme an, dass die Datenbank exampledb auf System 1 bereits vorhanden ist und Tabellen mit Einträgen enthält. Also müssen wir eine leere Datenbank mit der gleichen Bezeichnung wie für die vorhandene Datenbank auf System 1 erstellen.

mysql -u root -p


CREATE DATABASE exampledb;
quit;

3 Replication

3.1 Firewall Konfiguration auf beiden Systemen

Die Versionen von system-config-firewall-tui vor 1.0.12-4.x wiesen im Zusammenhang mit individuellen Regeln (sie wurden nicht angewendet) einen Fehler auf - überprüfe also welche Version auf Deinem System installiert ist.

yum list installed | grep firewall

Falls die installierte Version älter ist als 1.0.12-4.x musst Du sie mit der neusten Version aktualisieren. Als diese Anleitung verfasst wurde, war die neuste Version nur in der updates-testing Paketdatenbank verfügbar.

yum --enablerepo=updates-testing update system-config-firewall-tui

Damit sich die mysql Server verbinden können, musst Du Port 3306 (tcp) auf beiden Systemen öffnen.

system-config-firewall

Klicke auf "Customize".


Gib den MySQL-Port in den Bereich "Other Ports" ein, wie auf dem unteren Screenshot gezeigt wird und klicke auf "OK" um die Einstellungen zu speichern.


Klicke auf "OK".


3.2 Log Verzeichnis auf beiden Systemen

Damit der MySQL Server Log-Dateien erstellen kann, müssen wir ein Verzeichnis anlegen und den Eigentum an MySQL übergeben.

mkdir /var/log/mysql/
chown mysql:mysql /var/log/mysql/

3.3 MySQL Konfiguration

In den nächsten zwei Schritten passen wir die MySQL Konfiguration auf beiden Systemen für die Master-Master Replication an.

3.3.1 System 1

vi /etc/my.cnf

Füge folgende Zeilen dem Bereich [mysqld] hinzu:

server-id = 1
replicate-same-server-id = 0
auto-increment-increment = 2
auto-increment-offset = 1

master-host = 192.168.0.200
master-user = slave1_user
master-password = %mysql_slaveuser_password%
master-connect-retry = 60
replicate-do-db = exampledb

log-bin = /var/log/mysql/mysql-bin.log
binlog-do-db = exampledb

relay-log = /var/lib/mysql/slave-relay.log
relay-log-index = /var/lib/mysql/slave-relay-log.index

expire_logs_days = 10
max_binlog_size = 500M

Starte danach den MySQL Server neu.

/etc/init.d/mysqld restart


3.3.2 System 2

vi /etc/my.cnf

Füge folgende Zeilen dem Bereich [mysqld] hinzu:

server-id = 2
replicate-same-server-id = 0
auto-increment-increment = 2
auto-increment-offset = 2

master-host = 192.168.0.100
master-user = slave2_user
master-password = %mysql_slaveuser_password%
master-connect-retry = 60
replicate-do-db = exampledb

log-bin= /var/log/mysql/mysql-bin.log
binlog-do-db = exampledb

relay-log = /var/lib/mysql/slave-relay.log
relay-log-index = /var/lib/mysql/slave-relay-log.index

expire_logs_days = 10
max_binlog_size = 500M

Starte danach den MySQL Server neu.

/etc/init.d/mysqld restart


3.4 Exportiere den MySQL Dump auf System 1

Nun erstellen wir einen dump der vorhandenen Datenbank und transferieren es zu System 2.

mysql -u root -p


USE exampledb;
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;

Die Ausgabe sollte wie folgt aussehen. Notiere Dir die Datei und Position - Du wirst beides später brauchen.

+------------------+----------+---------------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+---------------------+------------------+
| mysql-bin.000004 | 98 | exampledb,exampledb | |
+------------------+----------+---------------------+------------------+
1 row in set (0.00 sec)

Öffne ein zweites Terminalfenster für System 1, erstelle einen dump und transferiere es zu System 2. Verlasse nicht die MySQL Kommandozeile - sonst verlierst Du die Schreibsperre.

cd /tmp/
mysqldump -u root -p%mysql_root_password% --opt exampledb > sqldump.sql
scp sqldump.sql root@192.168.0.200:/tmp/

Schließe danach das zweite Terminalfenster und wechsle zurück zum ersten. Entferne die Schreibsperre und verlasse die MySQL Kommandozeile.

UNLOCK TABLES;
quit;

3.5 Importiere den MySQL Dump auf System 2

Es wird Zeit den Datenbank dump auf System 2 zu importieren.

mysqladmin --user=root --password=%mysql_root_password% stop-slave
cd /tmp/
mysql -u root -p%mysql_root_password% exampledb < sqldump.sql

3.6 System 2 als Master

Nun benötigen wir Informationen über den Master Status auf System 2.

mysql -u root -p
USE exampledb;
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;

Die Ausgabe sollte wie folgt aussehen. Notiere die Datei und Position - Du wirst beides später brauchen.

+------------------+----------+---------------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+---------------------+------------------+
| mysql-bin.000003 | 958 | exampledb,exampledb | |
+------------------+----------+---------------------+------------------+
1 row in set (0.00 sec)

Entferne danach die Schreibsperre.

UNLOCK TABLES;

Nun sind wir bereit Master für das System 1 zu werden. Ersetze %mysql_slaveuser_password% mit dem Passwort, welches Du ausgewählt hast und pass auf, dass Du die Werte für MASTER_LOG_FILE und MASTER_LOG_POS mit den Werten, die Du in Schritt 3.4 notiert hast, ersetzt!

CHANGE MASTER TO MASTER_HOST='192.168.0.100', MASTER_USER='slave2_user', MASTER_PASSWORD='%mysql_slaveuser_password%', MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=98;

Starte nun den Slave ...

START SLAVE;

... und sieh Dir den Slave Status an. Es ist sehr wichtig, dass beide, Slave_IO_Running und Slave_SQL_Running auf Yes gesetzt sind. Sind sie es nicht, ist etwas schief gelaufen und Du solltest Dir die Logs ansehen.

SHOW SLAVE STATUS;


+----------------------------------+---------------+-------------+-------------+---------------+------------------+---------------------+--------------------+---------------+-----------------------+------------------+-------------------+---------------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+
| Slave_IO_State | Master_Host | Master_User | Master_Port | Connect_Retry | Master_Log_File | Read_Master_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Master_Log_File | Slave_IO_Running | Slave_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Master_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Master_SSL_Allowed | Master_SSL_CA_File | Master_SSL_CA_Path | Master_SSL_Cert | Master_SSL_Cipher | Master_SSL_Key | Seconds_Behind_Master | +----------------------------------+---------------+-------------+-------------+---------------+------------------+---------------------+--------------------+---------------+-----------------------+------------------+-------------------+---------------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+ | Waiting for master to send event | 192.168.0.100 | slave2_user | 3306 | 60 | mysql-bin.000004 | 98 | slave-relay.000002 | 235 | mysql-bin.000004 | Yes | Yes | exampledb,exampledb | | | | | | 0 | | 0 | 98 | 235 | None | | 0 | No | | | | | | 0 | +----------------------------------+---------------+-------------+-------------+---------------+------------------+---------------------+--------------------+---------------+-----------------------+------------------+-------------------+---------------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+ 1 row in set (0.00 sec)
Verlasse danach die MySQL Kommandozeile.

quit;

3.7 System 1 als Master

Öffne eine MySQL Kommandozeile auf System 1 ...

mysql -u root -p

... und halte den Slave an.

STOP SLAVE;

Nun sind wir bereit Master für das System 2 zu werden. Ersetze %mysql_slaveuser_password% mit dem Passwort, das Du gewählt hast und pass auf, dass Du die Werte für MASTER_LOG_FILE und MASTER_LOG_POS mit den Werten, die Du in Schritt 3.6 notiert hast, ersetzt!

CHANGE MASTER TO MASTER_HOST='192.168.0.200', MASTER_USER='slave1_user', MASTER_PASSWORD='%mysql_slaveuser_password%', MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=958;

Starte nun den Slave ...

START SLAVE;

... und sieh Dir den Slave Status an. Es ist sehr wichtig, dass beide, Slave_IO_Running und Slave_SQL_Running auf Yes. gesetzt sind. Sind sie es nicht, ist etwas schief gelaufen und Du solltest Dir die Logs ansehen.

SHOW SLAVE STATUS;


+----------------------------------+---------------+-------------+-------------+---------------+------------------+---------------------+--------------------+---------------+-----------------------+------------------+-------------------+---------------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+
| Slave_IO_State | Master_Host | Master_User | Master_Port | Connect_Retry | Master_Log_File | Read_Master_Log_Pos | Relay_Log_File | Relay_Log_Pos | Relay_Master_Log_File | Slave_IO_Running | Slave_SQL_Running | Replicate_Do_DB | Replicate_Ignore_DB | Replicate_Do_Table | Replicate_Ignore_Table | Replicate_Wild_Do_Table | Replicate_Wild_Ignore_Table | Last_Errno | Last_Error | Skip_Counter | Exec_Master_Log_Pos | Relay_Log_Space | Until_Condition | Until_Log_File | Until_Log_Pos | Master_SSL_Allowed | Master_SSL_CA_File | Master_SSL_CA_Path | Master_SSL_Cert | Master_SSL_Cipher | Master_SSL_Key | Seconds_Behind_Master | +----------------------------------+---------------+-------------+-------------+---------------+------------------+---------------------+--------------------+---------------+-----------------------+------------------+-------------------+---------------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+ | Waiting for master to send event | 192.168.0.200 | slave1_user | 3306 | 60 | mysql-bin.000003 | 958 | slave-relay.000002 | 235 | mysql-bin.000003 | Yes | Yes | exampledb,exampledb | | | | | | 0 | | 0 | 958 | 235 | None | | 0 | No | | | | | | 0 | +----------------------------------+---------------+-------------+-------------+---------------+------------------+---------------------+--------------------+---------------+-----------------------+------------------+-------------------+---------------------+---------------------+--------------------+------------------------+-------------------------+-----------------------------+------------+------------+--------------+---------------------+-----------------+-----------------+----------------+---------------+--------------------+--------------------+--------------------+-----------------+-------------------+----------------+-----------------------+ 1 row in set (0.00 sec)
Verlasse danach die MySQL Kommandozeile.

quit;

Wenn alles gut gegangen ist, funktioniert die Master-Master Replication nun. Überprüfe Deine Logs auf beiden Systemen falls Probleme auftreten sollten.

4 Links