Heute gibts mal einen kleinen Schnellkurs zum Thema MySQL-Replikation.
Die Master-Slave-Replikation wird gerne verwendet, wenn es hauptsächlich um Daten- und Ausfallsicherheit der Datenbank geht. Der Hauptvorteil dieser Replikationsart ist, dass die Sicherung der Daten auf mindestens eine zweite Datenbank quasi “on-the-fly” passiert. Außerdem wird ein sicherer Export der kompletten Daten ohne Ausfall auf Kundenseite möglich.
Schreibzugriffe erfolgen dabei ausschließlich auf dem Master-Server, Lesezugriffe können auf Master- wie Slave-Server erfolgen. Die Verteilung der Schreibzugriffe geschieht wie folgt:
- Jeder Schreibzugriff wird auf dem Master mit einer eindeutigen Positions-ID in ein binäres Logfile (bin.log) geschrieben
- Jeder Slave fragt den Master regelmäßig nach neuen Einträgen in diesem Logfile
- Liegen Änderungen vor, werden diese auf jedem Slave in eine Datei (relay.log) geschrieben
- Die nun neue, letzte dem Slave bekannte Position des bin.logs wird in master.info auf dem Slave gespeichert.
- Die letztn Änderungen im relay.log werden nun auf dem Slave ausgeführt, wobei die Daten nochmals aus Sicherheitsgründen mit dem Master verglichen werden
- Treten bei der Replikation Probleme auf, werden diese in error.log festgehalten und die Replikation bleibt stehen.
Wie setze ich nun so eine Replikation auf?
Zunächst einmal legen wir einen Replikationsuser an, mit dem sich die Datenbanken untereinander verbinden können. Das machen wir sowohl auf dem Master:
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.*
TO 'replication'@'slave-host' IDENTIFIED BY 'passwort'
wie dem Slave:
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.*
TO 'replication'@'master-host' IDENTIFIED BY 'passwort'
Damit können wir notfalls auch vom Slave auf den Master replizieren, falls der Master einmal ausgefallen ist und der Slave übernommen hat.
Jetzt konfigurieren wir den Master (/etc/mysql/my.cnf):
server-id = 1 # ID des Servers, muss eindeutig sein
log-bin = /var/log/mysql/bin.log # Binäres Logfile
expire_logs_days = 10 # nach wieviel Tagen die logs gelöscht werden sollen
max_binlog_size = 100M # Maximale Größe einer einzelnen Logdatei
binlog_do_db = Datenbank-Name # Begrenzung des Binlogs auf eine DB
Ein Neustart der Datenbank kann direkt erfolgen, damit die Konfiguration greift.
Jetzt ist der Slave dran (/etc/mysql/my.cnf):
server-id = 2
master-host = 192.168.0.1 # IP der Master-DB
master-port = 3306
master-user = replication
master-password = passwort
replicate-do-db = Datenbank-Name
# Nur diese DB in relay.log übernehmen
binlog_do_db = Datenbank-Name
# Nur diese DB in bin.log übernehmen
expire_logs_days = 10
max_binlog_size = 100M
log-bin = /var/log/mysql/bin.log
log-bin-index = /var/log/mysql/log-bin.index
log-error = /var/log/mysql/error.log
relay-log = /var/log/mysql/relay.log
relay-log-info-file = /var/log/mysql/relay-log.info
relay-log-index = /var/log/mysql/relay-log.index
Die Slave-DB nun einmal neu starten.
Der Slave spielt hier wie gesagt 2 Rollen: Er ist Slave (relay.log), schreibt aber auch gleichzeitig bin.logs, um im Notfall die Datenbasis für eine Masterrolle zu haben.
Ich gehe nun davon aus, dass der Master schon irgendwelche sinnvollen Daten hat und der Slave sich in einem undefinierten Zustand befindet. Vielleicht hat er schon ein paar Daten, vielleicht nicht. Nur Folgendes muss gegeben sein: Die zu replizierenden Datenbanken sind auch auf dem Slave grundsätzlich vorhanden. Dann können wir folgendes Skript auf dem Master ausführen. Ich gehe davon aus, dass es in /root/bin liegt und von dort ausgeführt wird und der MySQL-User “root” die Berechtigung besitzt, sich vom Master auf den Slave-Server connecten zu dürfen:
#! echo "Dumpe Datenbank XY ..."
mysqldump --user=root --password=Passwort \
--extended-insert --master-data \
fotouristen > /root/bin/replication.sql
echo "" echo "Koiere Dump auf slave-host..."
scp /root/bin/replication.sql slave-host:
echo
echo "Stoppe MySQL-Slave auf slave-host..."
ssh slave-host mysqladmin -uroot -pPasswort stop-slave
echo
echo "Importiere Dump auf slave-host..."
ssh slave-host "mysql -uroot -pPasswort \
Datenbank-Name < /root/replication.sql"
echo
echo "Starte MySQL-Slave auf slave-host..."
ssh slave-host mysqladmin -uroot -pPasswort start-slave
echo
echo "Lösche temporäre Dateien..."
rm /root/bin/replication.sql
ssh slave-host /root/replication.sql
echo
echo "done!"
Das wars!
Der Slave sollte nun in Sync mit dem Master sein. Ein Blick in /var/log/mysql/error.log sollte Aufschluss darüber geben.
Es gibt viele Wege Master und Slave zu synchronisieren. Der Einfachheit sei an dieser Stelle noch gesagt, dass obiges Script auch dazu verwendet werden kann, einen “out-of-sync”-Slave damit ohne weiteres Zutun wieder an den Start zu bringen. Für die Dauer des Dumps ist der Master währenddessen jedoch nicht erreichbar.