MySQL Replikation
Heute möchte ich euch die Replikation unter MySQL 5.0 vorstellen. Als erstes möchte ich auf zwei Begriffe eingehen, welche Hauptbestandteil der Replikation sind.
Master und Slave
Der Master ist der Hauptdatenbankserver. Wie der Name schon sagt ist das der Meister, der den Ton angibt. Der Slave sozusagen, der arme Sklave, ist ein zweiter Datenbankserver, der die ganze Arbeit macht, was Ihm der Meister befiehlt.
Ich beschreibe hier den einfachsten Fall der Replikation mit einem Master und einem Slave und werde nicht auf verschiedene Replikations Topologien eingehen.
MySQL unterscheidet unter der Anweisungsbasierten und Zeilenbasierten Replikation. Ich beschreibe in meinem Artikel die Replikation unter MySQL 5.0.X, und die Zeilenbasierte Replikation wurde erst ab der Version 5.1 implementiert.
Wofür braucht man die Replikation? Einige Anwendungsälle der Replikation sind:
Hochverfügbarkeit, Failover und Loadbalancing
Der Lastenausgleich kann die Leseabfragen einer Anwendung über mehrere Server verteilen.
Backups
Replikation bietet eine Möglichkeit zur Unterstützung von Backups. Die Replikation ist aber auf keinen Fall ein Ersatz für ein richtiges Sicherungskonzept.
Testen von MySQL Upgrades – Live Testumgebungen -
Man kann ein Slave auf eine neue Version Upgraden und überprüfen ob die Anwendung funktioniert, bevor man den Master und die weiteren Slaves aktualisiert oder zur Schulungszwecken eine Anwendung auf dem Slave testen.
Mein Artikel basiert auf MySQL 5.051a unter Linux Debian 5.0 Lenny.
Als erstes instalieren wir den MySQL Server aus den Repositorys.
aptitude install mysql-server-5.0
Mit dem Paket wird auch noch der MySQL Client installiert. In dem Bild kann man weitere Abhängigkeiten sehen.
Wir starten den MySQL Server mit /etc/init.d/mysql start
Etwas zu der Verzeichnisstruktur von Mysql.
Im /usr/bin/ Verzeichnis wird der Datenbankserver mit allen Programmen installiert.
ls -lh /usr/bin/my*
-rwxr-xr-x 1 root root 1,6M 13. Feb 11:57 /usr/bin/myisamchk
-rwxr-xr-x 1 root root 1,5M 13. Feb 11:56 /usr/bin/myisam_ftdump
-rwxr-xr-x 1 root root 1,5M 13. Feb 11:57 /usr/bin/myisamlog
-rwxr-xr-x 1 root root 1,5M 13. Feb 11:57 /usr/bin/myisampack
-rwxr-xr-x 1 root root 1,3M 13. Feb 11:57 /usr/bin/my_print_defaults
-rwxr-xr-x 1 root root 76K 13. Feb 11:56 /usr/bin/mysql
-rwxr-xr-x 1 root root 109K 13. Feb 11:55 /usr/bin/mysqlaccess
-rwxr-xr-x 1 root root 29K 13. Feb 11:56 /usr/bin/mysqladmin
lrwxrwxrwx 1 root root 10 3. Mär 22:18 /usr/bin/mysqlanalyze -> mysqlcheck
-rwxr-xr-x 1 root root 88K 13. Feb 11:56 /usr/bin/mysqlbinlog
-rwxr-xr-x 1 root root 12K 13. Feb 11:55 /usr/bin/mysqlbug
-rwxr-xr-x 1 root root 20K 13. Feb 11:56 /usr/bin/mysqlcheck
-rwxr-xr-x 1 root root 332K 13. Feb 11:56 /usr/bin/mysql_client_test
-rwxr-xr-x 1 root root 6,4M 13. Feb 11:56 /usr/bin/mysql_client_test_embedded
-rwxr-xr-x 1 root root 3,8K 13. Feb 11:55 /usr/bin/mysql_convert_table_format
-rwxr-xr-x 1 root root 23K 13. Feb 11:55 /usr/bin/mysqld_multi
-rwxr-xr-x 1 root root 13K 13. Feb 11:56 /usr/bin/mysqld_safe
-rwxr-xr-x 1 root root 64K 13. Feb 11:56 /usr/bin/mysqldump
-rwxr-xr-x 1 root root 6,3K 13. Feb 11:55 /usr/bin/mysqldumpslow
-rwxr-xr-x 1 root root 12K 13. Feb 11:55 /usr/bin/mysql_explain_log
-rwxr-xr-x 1 root root 3,2K 13. Feb 11:55 /usr/bin/mysql_find_rows
-rwxr-xr-x 1 root root 483 13. Feb 11:55 /usr/bin/mysql_fix_extensions
-rwxr-xr-x 1 root root 5,8K 13. Feb 11:55 /usr/bin/mysql_fix_privilege_tables
-rwxr-xr-x 1 root root 33K 13. Feb 11:55 /usr/bin/mysqlhotcopy
-rwxr-xr-x 1 root root 16K 13. Feb 11:56 /usr/bin/mysqlimport
-rwxr-xr-x 1 root root 13K 13. Feb 11:55 /usr/bin/mysql_install_db
lrwxrwxrwx 1 root root 10 3. Mär 22:18 /usr/bin/mysqloptimize -> mysqlcheck
lrwxrwxrwx 1 root root 10 3. Mär 22:18 /usr/bin/mysqlrepair -> mysqlcheck
-rwxr-xr-x 1 root root 35K 13. Feb 11:56 /usr/bin/mysqlreport
-rwxr-xr-x 1 root root 6,5K 13. Feb 11:55 /usr/bin/mysql_secure_installation
-rwxr-xr-x 1 root root 17K 13. Feb 11:55 /usr/bin/mysql_setpermission
-rwxr-xr-x 1 root root 20K 13. Feb 11:56 /usr/bin/mysqlshow
-rwxr-xr-x 1 root root 15K 13. Feb 11:55 /usr/bin/mysql_tableinfo
-rwxr-xr-x 1 root root 136K 13. Feb 11:56 /usr/bin/mysqltest
-rwxr-xr-x 1 root root 6,2M 13. Feb 11:56 /usr/bin/mysqltest_embedded
-rwxr-xr-x 1 root root 32K 13. Feb 11:56 /usr/bin/mysqltestmanager
-rwxr-xr-x 1 root root 8,0K 13. Feb 11:56 /usr/bin/mysqltestmanagerc
-rwxr-xr-x 1 root root 6,9K 13. Feb 11:56 /usr/bin/mysqltestmanager-pwgen
-rwxr-xr-x 1 root root 1,3M 13. Feb 11:56 /usr/bin/mysql_tzinfo_to_sql
-rwxr-xr-x 1 root root 48K 13. Feb 11:57 /usr/bin/mysql_upgrade
-rwxr-xr-x 1 root root 5,7K 13. Feb 11:55 /usr/bin/mysql_upgrade_shell
-rwxr-xr-x 1 root root 94K 13. Feb 11:56 /usr/bin/mysql_waitpid
-rwxr-xr-x 1 root root 3,8K 13. Feb 11:55 /usr/bin/mysql_zap
Im Verzeichnis /var/lib/mysql/ befinden sich die Datenbanken logfiles und die pid Datei.
ls -lh /var/lib/mysql/
insgesamt 21M
-rw-r–r– 1 root root 0 3. Mär 22:18 debian-5.0.flag
-rw-rw—- 1 mysql mysql 5 15. Mär 23:41 debvm.pid
-rw-rw—- 1 mysql mysql 10M 15. Mär 23:40 ibdata1
-rw-rw—- 1 mysql mysql 5,0M 15. Mär 23:41 ib_logfile0
-rw-rw—- 1 mysql mysql 5,0M 3. Mär 22:18 ib_logfile1
drwxr-xr-x 2 mysql root 4,0K 3. Mär 23:19 mysql
-rw——- 1 root root 7 3. Mär 22:18 mysql_upgrade_info
drwx—— 2 mysql mysql 4,0K 3. Mär 23:19 secondworld
drwx—— 2 mysql mysql 4,0K 3. Mär 23:19 world
Im Verzeichnis /etc/mysql/ befinden sich die Konfigurationsdateien von MySQL
ls -lh /etc/mysql/
insgesamt 20K
drwxr-xr-x 2 root root 4,0K 3. Mär 22:18 conf.d
-rw——- 1 root root 312 3. Mär 22:18 debian.cnf
-rwxr-xr-x 1 root root 1,2K 13. Feb 11:56 debian-start
-rw-r–r– 1 root root 1,8K 15. Mär 22:36 my.cnf
-rw-r–r– 1 root root 3,8K 3. Mär 22:55 org.my.cnf
Die Konfigurationsdatei von dem MySQL Server ist die my.cnf, welche ich in org.my.cnf verschoben habe. Ich habe eine neu angepasste Datei erstellt, auf welche wir später näher eingehen, wobei ich nur den Teil für die Replikation beschreiben werde. Schließlich möchte ich noch weitere Artikel zu MySQL verfassen.
Als erstes muss ich den Master konfigurieren. Dazu bearbeite ich die /etc/mysql/my.cnf
(Bei den meisten Distributionen befindet sich die Datei direkt im /etc Verzeichnis)
Die Konfiguration auf dem Master ist :
#Master Replikationseinstellungen.
server-id = 10
log-bin = mysql-bin
log-bin-index = mysql-bin.index
relay_log = mysql-relay-bin
relay-log-index = mysql-relay-bin.index
expire_logs_days = 5
sync_binlog=1
Beschreibung zu den Variablen:
server-id
Jeder MySQL Server braucht eine eindeutige Server-id. Bei jeder Installation ist die „1“ als Vorgabe . Damit kann man eine Fehlerquelle ausschließen, wenn man die Server-id auf einen anderen Wert ändert. Der Master und der Slave müssen unterschiedliche Id’s haben. Eine gute Regel wäre das letzte Oktett der IP Adresse. Wenn der Master die IP Adresse „192.168.0.55 hat, würde man als server-id auf dem Master die 55 eintragen.
log-bin
Die nächste Variable log-bin ist standardmäßig immer aktiviert und als Vorgabe ist da kein Wert eingetragen. Damit wird sozusagen das Binärlog eingeschaltet. Das Binärlog wird für die Replikation gebraucht. In dem Binärlog werden fast alle SQL Anweisungen aufgezeichnet. Das Binälog wird aber auch für Point in Time Recovery gebraucht, weshalb man diese Variable immer eingeschaltet haben sollte, auch wenn keine Replikation eingesetzt wird. Ich vergebe der Variable immer einen Dateinamen als Wert. Standardmäßig wenn da nichts steht wird das Binärlog nach dem Hostnamen des Servers benannt und könnte zu Problemen führen,wenn sich der Hostname ändert. Um eine zusätzliche Fehlerquelle auszuschließen vergebe ich einen Namen.
log-bin-index
Diese Variable kann den Dateinamen für die index Datei beeinflussen. In der mysql-bin.index Datei steht in jeder Zeile der Dateiname der Binälogdatei.
relay_log
Über diese Variable wird wiederum der Dateiname festgelegt. Die Variable ist für den Slave relevant. Der Slave liest das Binärlog des Masters und schreibt die Daten in sein Relaylog auf die Festplatte, bevor es abgespielt wird.
relay-log-index
Hier wird wieder der Dateiname festgelegt. In der Index Datei wird festgelegt, welche Relay-Log Datei gerade verwendet wird.
expire_logs_days
Mit dieser Variable kann man seine Binärlogs aufräumen. Ich finde diese Variable sollte man auf jeden Fall einsetzen, obwohl sie für die Replikation nicht wichtig ist. Bei einer großen Datenbank bzw. bei vielen updates könnte es passieren, dass die Festplatte voll läuft. Der Wert wird in Tagen angegeben. In meinem Beispiel werden die Logs fünf Tage lang vorgehalten.
sync_binlog=1
Die Einstellung veranlasst MySQL den Inhalt des Binärlogs auf die Festplatte zu synchronisieren, damit im Falle eines Absturzes keine Log Events verloren gehen. Die Variable ist für das Binärlog zuständig und nicht für das Relaylog. Bei dieser Konstellation mit einem Master und einem Slave wird diese Variable auf dem Slave nicht benötigt.
Ich habe ein kleines Schaubild zur der Replikation erstellt.
Nachdem wir die Konfigurationsdatei bearbeitet haben, muss noch ein Benutzer auf dem Master eingerichtet werden.
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO ‘replik_user’@’192.168.0.%’ identified by ‘strenggeheim’;
Zum Schluss muss noch der MySQL Server durchgestartet werden, damit die Änderung wirksam werden.
Jetzt muss noch der SLAVE eingerichtet werden.
Auf dem Slave bearbeiten wir wieder die /etc/mysql/my.cnf Datei.
Die Replikationsparameter sind ähnlich der auf dem Master.
Theoretisch reicht auf dem Slave nur die Variable server-id mit einer anderen ID als auf dem Master. Ich habe folgende Konfiguration.
#Slave Replikationseinstellungen.
server-id = 250
log-bin = mysql-bin
log-bin-index = mysql-bin.index
relay_log = mysql-relay-bin
relay-log-index = mysql-relay-bin.index
log_slave_updates = 1
skip_slave_start
expire_logs_days = 5
skip_slave_start
Mit der Option wird verhindert, dass der Slave nach einem Absturz oder Neustart automatisch den Slave startet.
log_slave_updates
Damit schreibt der Slave die replizierten Events in sein eigenes Binärlog.
Anmerkung: Man kann auch die Angaben zu den Logs absolut eingeben. Unter CentOS 5.2 konnte ich so ein Fehler beseitigen.
log-bin = /var/lib/mysql/mysql-bin
relay_log = /var/lib/mysql/mysql-relay-bin
Das geht natürlich nicht, wenn die eine my.cnf für mehrere Instanzen benutzt wird.
Auf dem Slave kann man noch beeinflussen, welche Datenbank repliziert werden soll. Wenn es auf dem Master fünf Datenbank gibt, so kann man mit „replicate_do_db = world“ beeinflussen, dass nur die Datenbank world repliziert wird. Zu diesem Punkt sollten Sie auf jeden Fall noch die Anmerkung zur der Standard DB im Handbuch lesen.
Nachdem wir auf dem Slave die Einstellungen vorgenommen haben, wird noch ein Benutzer erstellt. Auf dem Slave erstellen wir den gleichen Replikationsbenutzer wie auf dem Master, obwohl dieser nicht benötigt wird. Man kann aber dadurch, dass die Einstellungen von dem Master und Slave fast gleich sind, einfacher die Rollen tauschen.
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO ‘replik_user’@’192.168.0.%’ identified by ‘strenggeheim’;
Natürlich muss der MySQL Server nach den Änderungen durchgestartet werden.
Bevor man die Replikation startet muss man zuerst den gleichen Datenbestand auf dem Slave, wie auf dem Master haben. Ich mache ein dump von der Datenbank auf dem Master, übertrage diesen auf den Slave und starte den slave mit den Parametern, welche Sie zuvor auf dem Master abgefragt haben. Das Problem dabei ist, dass man in der Zeit bis man den Slave startet auf dem Master die Daten nicht verändern darf. Ich empfehle eine etwas andere Vorgehensweise.
Auf dem Slave vergebe ich die Parameter für die Replikation ohne das Master_Logfile und Master_logfile_Postion.
In meinem Beispiel sind folgende IP Adressen für dem Master und Slave.
Master IP Adresse: „192.168.0.10“
Slave IP Adresse: „192.168.0.250“
Unter dem MySQL Monitor müssen wir den Slave zurücksetzen bevor wir die Replikationsparameter übergeben können. Der Slave lief die ganze Zeit mit den Standardwerten und ich habe dem Relaylog und Binärlog einen anderen Namen vergeben, sodass die alten Werte resetet werden müssen. Ich gebe auf dem MySQL Monitor folgenden Befehl ein.
RESET SLAVE;
RESET MASTER;
Wir erstellen auch noch eiene leere Datenbank in welche wir dann das Sqldump einspielen.
CREATE DATABASE world;
Jetzt können wir mit der Replikation fortfahren.
CHANGE MASTER TO
MASTER_HOST=’192.168.0.10′,
MASTER_USER=’replik_user’,
MASTER_PASSWORD=’strenggeheim’,
MASTER_PORT=3306;
Wichtig bitte die Hochkommata und den Semikolon am ende beachten.
Wir erstellen auf dem Master ein Dump mit der master-data Option. Wenn Sie mein anderen Artikel zu myslqdum gelesen haben, dann können Sie die Sicherung, welche jeden Abend erstellt wird, per scp auf den Slave kopieren.
Auf dem Master aus der Shell können sie den folgenden Befehl ausführen und die erstellte Datei auf den Slave rüber kopieren.
mysqldump –master-data -uroot -pgeheim world >/tmp/world_2010-25.03.sql
Alternativ kann man auch auf dem Slave ein Dump erstellen, allerdings mit einem anderen Benutzer, welcher das Recht „SUPER“ hat. Bei dem Parameter master-data und socket sind es zwei Minus Zeichen.
Auf dem Slave aus der Shell geben wir dann den folgenden Befehl ein.
mysqldump –master-data -h192.168.0.10 -uadmin -psuper –socket=/var/lib/mysql/mysql.sock world >/tmp/world_2010-25.03.sql
Mit dem Parameter – -master-data wird in dem dump das Master Logfile und Master Logfile Postition eingetragen. Vorsicht gleichzeitig werden dabei die Tabellen gelockt.
Nachdem wir den Dump auf dem Slave haben, können wir unabhängig davon ob Benutzer auf dem Master arbeiten oder nicht, die Replikation starten.
Aus der Shell geben wir den folgenden Befehl an.
mysql -uroot -pgeheim –socket=/var/lib/mysql/mysql.sock world < /tmp/world_2010-25.03.sql
In dem Mysql Monitor überprüfe ich den Status und die Datenbank und starte die Replikation.
show tables from world;
show slave status \G
Anstatt des Semikolons kann ich mit dem Parameter „\G“, um es besser lesen zu können, die Ausgabe in vertikaler Schreibweise anzeigen lassen. Das schont die Augen
Die beiden werte unter Slave_IO_Running und Slave_SQL_Running stehen noch auf NO.
Man kann auch beobachten, dass nach dem einpielen des dumps in Master_Log_File und Read_Master_Log_Pos die Werte von dem Master stehen.
Ich brauche jetzt nur noch den Slave zu starten und man kann beobachten, dass unter Exec_Master_Log_Pos sich die Werte ändern.
START SLAVE;
Wenn man beobachten möchte, welcher Datensatz jetzt repliziert wird empfehle ich
SHOW PROCESSLIST \G
Bei MySQL gibt es am 26.03.2010 ein Webinar zur der Replikation.
Quellen:
Tags: Datenbanken, DBMS, Master, MySQL, OpenSource, Replikation, Slave, Tutorial


412 comments so far
Leave a reply