Generell erfordert die Replikationskompatibilität auf SQL-Ebene,
dass alle verwendeten Funktionen sowohl vom Master als auch vom
Slave unterstützt werden. Wenn Sie eine Funktion auf einem
Master-Server verwenden, die nur ab einer bestimmten MySQL-Version
verfügbar ist, dann können Sie keine Replikation auf einen Slave
vornehmen, der älter ist als diese Version. Derartige
Inkompatibilitäten treten häufig zwischen verschiedenen Serien
auf. So können Sie beispielsweise keine Replikation von MySQL
5.1 auf 5.0 durchführen. Allerdings
können solche Inkompatibilitäten auch innerhalb derselben Serie
auftreten. So ist beispielsweise die Funktion
SLEEP()
seit MySQL 5.0.12 verfügbar. Wenn Sie
diese Funktion auf dem Master-Server verwenden, können Sie sie
nicht auf einen Slave replizieren, der älter ist als MySQL
5.0.12.
Beabsichtigen Sie, die Replikation zwischen MySQL 5.1 und einer älteren Version durchzuführen, dann sollten Sie im MySQL-Referenzhandbuch zu dieser älteren Release-Serie nach Informationen zu den Replikationseigenschaften dieser Serie suchen.
Die folgende Liste enthält genauere Angaben dazu, was
unterstützt wird und was nicht. Zusätzliche
InnoDB
-spezifische Informationen zur
Replikation finden Sie in
Abschnitt 14.2.6.5, „InnoDB
und MySQL-Replikation“.
Bei der klassischen anweisungsbasierten Replikation kann es Probleme mit der Replikation gespeicherter Routinen geben. Diese Probleme können Sie umgehen, indem Sie stattdessen die datensatzbasierte Replikation benutzen. Eine umfassende Liste möglicher Probleme finden Sie unter Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“. Eine Beschreibung der datensatzbasierten Replikation finden Sie in Abschnitt 6.3, „Zeilenbasierte Replikation“.
Die Replikation von AUTO_INCREMENT
-,
LAST_INSERT_ID()
- und
TIMESTAMP
-Werten erfolgt korrekt.
Die Funktionen USER()
,
UUID()
und LOAD_FILE()
werden ohne Änderung repliziert und funktionieren daher nur
dann korrekt auf dem Slave, wenn die datensatzbasierte
Replikation aktiviert ist. (Siehe auch
Abschnitt 6.3, „Zeilenbasierte Replikation“.)
Die folgende Beschränkung gilt nur für die
anweisungsbasierte, nicht für die datensatzbasierte
Replikation. Die Funktionen
GET_LOCK()
,
RELEASE_LOCK()
,
IS_FREE_LOCK()
und
IS_USED_LOCK()
, die Sperren auf
Benutzerebene verwalten, werden repliziert, ohne dass der
Slave den zugehörigen Kontext auf dem Master kennt. Aus
diesem Grund sollten diese Funktionen nicht zum Einfügen in
eine Tabelle auf dem Master verwendet werde, da der Kontext
auf dem Slave ganz anders aussehen würde. (So sollten Sie
etwa keine Anweisung wie INSERT INTO mytable
VALUES(GET_LOCK(...))
absetzen.)
Die Variablen FOREIGN_KEY_CHECKS
,
SQL_MODE
, UNIQUE_CHECKS
und SQL_AUTO_IS_NULL
werden (ab MySQL 5.0)
alle repliziert. Die Systemvariable
storage_engine
(die auch
table_type
heißt) wird in MySQL 5.1 noch
nicht repliziert, was für die Replikation zwischen
verschiedenen Speicher-Engines von Vorteil ist.
Die Replikation funktioniert zwischen Mastern und Slaves unter MySQL 5.0 und 5.1 in beliebiger Kombination – auch dann, wenn Master und Slave unterschiedliche Werte für die Zeichensatz- und/oder die globalen Zeitzonenvariablen aufweisen. (Beachten Sie, dass dies nicht in Fällen zutrifft, in denen Master und/oder Slave unter MySQL 4.1 oder früher laufen.)
Folgendes gilt für die Replikation zwischen MySQL Servern, die unterschiedliche Zeichensätze benutzen:
Wenn der Master MySQL 4.1 verwendet, müssen Sie
immer dieselben
globalen Werte für Zeichensatz und
Sortierfolge auf dem Master und dem Slave verwenden –
unabhängig davon, welche MySQL-Version auf dem Slave
läuft. (Diese werden von den Optionen
--character-set-server
und
--collation-server
gesteuert.)
Andernfalls kann es Fehler aufgrund von
Schlüsseldubletten auf dem Slave geben, da ein
Schlüssel, der im Zeichensatz des Masters eindeutig ist,
dies im Zeichensatz des Slaves nicht unbedingt sein muss.
Beachten Sie, dass dies keine Rolle mehr spielt, wenn
Master und Slave beide unter MySQL 5.0 oder höher laufen.
Wenn der Master älter ist als MySQL 4.1.3, dann sollte
auf den beteiligten Clients kein anderer Zeichensatz als
der global angegebene verwendet werden, weil der Slave
eine solche Änderung des Zeichensatzes nicht bemerkt.
Clients sollten also SET NAMES
,
SET CHARACTER SET
usw. nicht benutzen.
Wenn sowohl Master als auch Slave unter 4.1.3 oder höher
laufen, können die Clients die zeichensatzbezogenen
Sitzungsvariablen frei einstellen, da diese Werte in das
Binärlog geschrieben und auf diese Weise dem Slave
mitgeteilt werden. Clients können also SET
NAMES
oder SET CHARACTER SET
verwenden oder Variablen wie
COLLATION_CLIENT
oder
COLLATION_SERVER
einstellen. Nicht
ändern können Clients hingegen den
globalen Wert dieser Variablen: Wie
bereits gesagt, Master und Slave müssen für den globalen
Zeichensatz immer identische Werte aufweisen.
Wenn sich auf dem Master Datenbanken mit Zeichensätzen
befinden, die sich vom globalen
character_set_server
-Wert
unterscheiden, dann sollten Sie Ihre CREATE
TABLE
-Anweisungen so formulieren, dass Tabellen
in diesen Datenbanken nicht implizit auf den
Standardzeichensatz der Datenbank angewiesen sind (siehe
auch Bug 2326). Ein guter Workaround hierfür besteht
darin, in der CREATE TABLE
-Anweisung
Zeichensatz und Sortierfolge explizit anzugeben.
Wenn der Master MySQL 4.1 verwendet, dann sollte auf Master
und Slave dieselbe Systemzeitzone eingestellt sein.
Andernfalls werden einige Anweisungen – wie etwa solche, die
die Funktionen NOW()
oder
FROM_UNIXTIME()
verwenden – nicht korrekt
repliziert. Sie können die Zeitzone, in der der MySQL Server
läuft, mit der Option
--timezone=
des Skripts timezone_name
mysqld_safe
oder durch
Einstellen der Umgebungsvariablen TZ
ändern. Master und Slave sollten ferner auch dieselbe
Standardeinstellung für die Verbindungszeitzone aufweisen,
d. h., der Wert des Parameters
--default-time-zone
sollte auf Master und
Slave gleich sein. Beachten Sie, dass dies nicht notwendig
ist, wenn der Master unter MySQL 5.0 oder höher läuft.
CONVERT_TZ(...,...,@session.time_zone)
wird
nur dann korrekt repliziert, wenn Master und Slave unter MySQL
5.0.4 oder höher laufen.
Sitzungsvariablen werden nicht korrekt repliziert, wenn sie in
Anweisungen verwendet werden, die Tabellen aktualisieren. So
fügt SET MAX_JOIN_SIZE=1000
gefolgt von
INSERT INTO mytable VALUES(@MAX_JOIN_SIZE)
auf dem Master nicht dieselben Daten ein wie auf dem Slave.
Dies betrifft allerdings nicht die gängige Sequenz aus
SET TIME_ZONE=...
gefolgt von
INSERT INTO mytable
VALUES(CONVERT_TZ(...,...,@time_zone))
.
Die Replikation von Sitzungsvariablen ist kein Problem, wenn die datensatzbasierte Replikation benutzt wird. Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“.
Es ist auch möglich, transaktionssichere Tabellen auf dem
Master in nichttransaktionssichere Tabellen auf dem Slave zu
replizieren. Sie können beispielsweise eine
InnoDB
-Tabelle auf dem Master als
MyISAM
-Tabelle auf dem Slave replizieren.
Allerdings kommt es, wenn Sie dies tun, zu Problemen, wenn der
Slave mitten in einem
BEGIN
/COMMIT
-Block
angehalten wird, weil er nachfolgend am Anfang des
BEGIN
-Blocks neu einstartet. Dieses Problem
steht auf unserer Aufgabenliste und wird in Bälde behoben
sein.
Änderungsanweisungen, die benutzerdefinierte Variablen (also
Variablen des Typs
@
)
referenzieren, werden korrekt repliziert. (Dies gilt jedoch
nicht für Versionen vor 4.1.) Beachten Sie, dass beginnend
mit MySQL 5.0 bei den Namen von Benutzervariablen die
Groß-/Kleinschreibung unterschieden wird, wenn Sie die
Replikation zwischen MySQL 5.0 und älteren Versionen
einrichten.
var_name
Slaves können unter Verwendung von SSL eine Verbindung zum Master herstellen.
Die globale Systemvariable
slave_transaction_retries
wirkt sich wie
folgt auf die Replikation aus: Wenn ein SQL-Thread auf einem
Replikationsslave eine Transaktion nicht ausführen kann, weil
eine InnoDB
-Blockade aufgetreten ist oder
die Werte innodb_lock_wait_timeout
von
InnoDB
bzw.
TransactionDeadlockDetectionTimeout
oder
TransactionInactiveTimeout
von
NDBCluster
überschritten wurden, erfolgt
die durch slave_transaction_retries
angegebene Anzahl von Neuversuchen, bevor der Vorgang mit
einer Fehlermeldung beendet wird. Der Standardwert ist 10. Die
Gesamtzahl der Neuversuche finden Sie in der Ausgabe von
SHOW STATUS
. (Siehe auch
Abschnitt 5.2.4, „Server-Statusvariablen“.)
Wenn eine der Tabellenoptionen DATA
DIRECTORY
oder INDEX DIRECTORY
in
einer CREATE TABLE
-Anweisung auf dem
Master-Server verwendet wird, wird dieselbe Option auch auf
dem Slave umgesetzt. Dies kann zu Problemen führen, wenn im
Dateisystem des Slave-Hosts kein entsprechendes Verzeichnis
vorhanden ist, oder wenn es zwar vorhanden ist, aber der
Slave-Server nicht darauf zugreifen kann. MySQL unterstützt
eine sql_mode
-Option namens
NO_DIR_IN_CREATE
. Wenn dieser SQL-Modus am
Slave-Server aktiviert ist, ignoriert der Slave die
Tabellenoptionen DATA DIRECTORY
und
INDEX DIRECTORY
beim Replizieren von
CREATE TABLE
-Anweisungen. Infolgedessen
werden die MyISAM
-Daten- und Indexdateien
im Datenbankverzeichnis der Tabelle erstellt.
Die folgende Beschränkung betrifft nur die anweisungsbasierte Replikation, nicht die datensatzbasierte Replikation: Die Daten auf dem Master und dem Slave können verschieden werden, wenn eine Abfrage so formuliert wird, dass die Datenänderung nichtdeterministisch ist, d. h. dem Gutdünken des Abfrageoptimierers überlassen wird. (Dies ist auch abgesehen von der Replikation nicht zu empfehlen.) Eine umfassende Erläuterung dieses Problems finden Sie unter Abschnitt A.8.1, „Offene Probleme in MySQL“.
FLUSH LOGS
, FLUSH
MASTER
, FLUSH SLAVE
und
FLUSH TABLES WITH READ LOCK
werden nicht
geloggt, weil dies bei der Replikation auf einen Slave
Probleme verursachen würde. Ein Syntaxbeispiel finden Sie in
Abschnitt 13.5.5.2, „FLUSH
“. Die Anweisungen FLUSH
TABLES
, ANALYZE TABLE
,
OPTIMIZE TABLE
und REPAIR
TABLE
werden in das Binärlog geschrieben und
infolgedessen auf die Slaves repliziert. Dies ist
normalerweise unproblematisch, weil diese Anweisungen die
Tabellendaten nicht verändern. Allerdings kann dies unter
bestimmten Umständen trotzdem Probleme verursachen. Wenn Sie
die Berechtigungstabellen in der
mysql
-Datenbank replizieren und diese
Tabellen direkt und ohne Verwendung von
GRANT
aktualisieren, müssen Sie eine
FLUSH PRIVILEGES
-Anweisung auf den Slaves
absetzen, damit die neuen Berechtigungen gültig werden.
Ferner müssen Sie, wenn Sie FLUSH TABLES
beim Umbenennen einer MyISAM
-Tabelle
absetzen, die Teil einer MERGE
-Tabelle ist,
auf den Slaves eine FLUSH TABLES
-Anweisung
manuell absetzen. Diese Anweisungen werden in das Binärlog
geschrieben, sofern Sie nicht
NO_WRITE_TO_BINLOG
oder den Alias
LOCAL
angegeben haben.
MySQL unterstützt genau einen Master und mehrere Slaves.
Zukünftig beabsichtigen wir, einen Votieralgorithmus
hinzuzufügen, der den Master automatisch wechselt, falls
Probleme in Verbindung mit dem aktuellen Master auftreten.
Ferner werden wir Agentenprozesse zur Durchführung einer
Lastverteilung implementieren, indem
SELECT
-Anweisungen an verschiedene Slaves
gesendet werden.
Wenn ein Server heruntergefahren wird und neu startet, werden
seine MEMORY
-Tabellen geleert. Der Master
repliziert diesen Effekt wie folgt auf seine Slaves: Wenn der
Master eine MEMORY
-Tabelle nach dem Start
zum ersten Mal verwendet, loggt er ein Ereignis, welches den
Slaves angibt, dass die Tabelle geleert werden muss, indem
eine DELETE
-Anweisung für die betreffende
Tabelle in das Binärlog geschrieben wird. Weitere
Informationen finden Sie in
Abschnitt 14.4, „Die MEMORY
-Speicher-Engine“.
Beachten Sie, dass das Folgende nicht gilt, wenn die datensatzbasierte Replikation verwendet wird, denn diese erfordert überhaupt keine Replikation von Temporärtabellen. (Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“.)
Temporärtabellen werden normalerweise repliziert. Eine Ausnahme liegt vor, wenn Sie den Slave-Server (und nicht nur die Slave-Threads) heruntergefahren und Temporärtabellen repliziert haben, die in Updates verwendet werden, welche noch nicht auf dem Slave ausgeführt wurden. Haben Sie den Slave-Server heruntergefahren, dann stehen die Temporärtabellen, die von diesen Aktualisierungen benötigt werden, beim Neustart des Servers nicht mehr zur Verfügung. Um dieses Problem zu umgehen, fahren Sie den Slave nicht herunter, solange Temporärtabellen geöffnet sind. Stattdessen wenden Sie folgende Vorgehensweise an:
Setzen Sie eine STOP SLAVE
-Anweisung
ab.
Überprüfen Sie mit SHOW STATUS
den
Wert der Variablen
Slave_open_temp_tables
.
Wenn der Wert 0 ist, beenden Sie den Slave mit einem mysqladmin shutdown-Befehl.
Ist der Wert nicht 0, dann starten Sie die Slave-Threads
mit START SLAVE
neu.
Wiederholen Sie den Vorgang nachfolgend so oft, bis die
Variable Slave_open_temp_tables
0 ist
und Sie den Slave beenden können.
Die Verbindung mit Servern in einer
Master/Slave-Zirkelbeziehung ist sicher, wenn Sie die Option
--log-slave-updates
benutzen. Das bedeutet,
dass Sie eine Konfiguration wie die folgende erstellen
können:
A -> B -> C -> A
Allerdings funktionieren viele Anweisungen in einer solchen Konfiguration nicht einwandfrei, sofern Ihr Code nicht so formuliert ist, dass potenzielle Probleme berücksichtigt werden, die aufgrund von auf verschiedenen Servern in unterschiedlicher Reihenfolge durchgeführten Updates entstehen können.
Serverkennungen werden in Binärlogereignisse kodiert, d. h.,
Server A erkennt, wenn ein Ereignis, das er liest,
ursprünglich von ihm selbst erstellt worden ist, und führt
es dann nicht aus (es sei denn, Server A wurde mit der Option
--replicate-same-server-id
gestartet, die
aber nur in wenigen Fällen wichtig ist). Es kommt also nicht
zu Endlosschleifen. Eine solche Zirkelkonfiguration
funktioniert nur, wenn Sie keine Updates durchführen, durch
die es zu Konflikten zwischen Tabellen kommt: Wenn Sie Daten
sowohl auf A als auch auf C einfügen, sollten Sie keinesfalls
einen Datensatz auf A einfügen, dessen Schlüssel unter
Umständen mit einem Datensatz auf C kollidiert. Ebenso wenig
sollten Sie dieselben Datensätze auf zwei Servern
aktualisieren, wenn die Reihenfolge, in der die Updates
durchgeführt werden, von Bedeutung ist.
Wenn eine Anweisung auf einem Slave einen Fehler erzeugt, wird
der Slave-SQL-Thread terminiert, und der Slave schreibt eine
Meldung in sein Fehlerlog. In diesem Fall sollten Sie manuell
eine Verbindung zum Slave herstellen und die Ursache des
Problems bestimmen. (Hierfür ist SHOW SLAVE
STATUS
recht praktisch.) Danach beheben Sie das
Problem (z. B. durch Erstellen einer nichtvorhandenen
Tabelle) und führen dann START SLAVE
aus.
Einen Master-Server herunterzufahren und später neu zu
starten ist sicher. Wenn ein Slave seine Verbindung zum Master
verliert, versucht er sofort eine Neuverbindung und wiederholt
diesen Versuch in regelmäßigen Abständen, bis er
erfolgreich ist. Standardmäßig erfolgt alle 60 Sekunden ein
Versuch zur Neuverbindung. Dies lässt sich mit der Option
--master-connect-retry
ändern. Ein Slave
kann auch mit Ausfällen der Netzwerkkonnektivität
zurechtkommen. Allerdings bemerkt er einen solchen Ausfall
erst, wenn er für slave_net_timeout
Sekunden keine Daten vom Master empfangen hat. Sind die
Ausfälle kurz, dann sollten Sie den Wert von
slave_net_timeout
verringern. Siehe auch
Abschnitt 5.2.2, „Server-Systemvariablen“.
Das (saubere) Herunterfahren des Slaves ist auch sicher, weil
er vermerkt, an welcher Stelle er beendet wurde. Unsauberes
Herunterfahren hingegen kann insbesondere dann Probleme
verursachen, wenn der Festplatten-Cache vor Terminierung des
Systems nicht auf die Festplatte geschrieben worden war. Ihre
Systemfehlertoleranz erhöht sich erheblich, wenn Sie eine
gute unterbrechungsfreie Stromversorgung verwenden. Eine
unsaubere Beendigung des Masters kann Inkonsistenzen zwischen
dem Inhalt der Tabellen und dem Binärlog auf dem Master zur
Folge haben. Dies lässt sich durch Verwendung von
InnoDB
-Tabellen und der Option
--innodb-safe-binlog
auf dem Master
vermeiden. Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.
Hinweis:
--innodb-safe-binlog
wird in MySQL 5.1 nicht
benötigt, weil es durch die in MySQL 5.0 eingeführte
Unterstützung von XA-Transaktionen obsolet geworden ist.
Siehe auch Abschnitt 13.4.7, „XA-Transaktionen“.
Aufgrund des nichttransaktionssicheren Wesens von
MyISAM
-Tabellen kann es vorkommen, dass
eine Anweisung eine Tabelle nur teilweise aktualisiert und
dann einen Fehlercode zurückgibt. Dies kann beispielsweise
beim Einfügen mehrerer Datensätze geschehen, wenn einer
dieser Datensätze gegen einen Schlüssel-Constraint
verstößt, oder wenn eine lange Update-Anweisung nach
Aktualisierung einer Anzahl von Datensätzen terminiert wurde.
Wenn dies auf dem Master passiert, wird der Slave-Thread
beendet. Es liegt dann am Datenbankadministrator, zu
entscheiden, was zu tun ist, sofern der Fehlercode nicht
zulässig ist und die Ausführung der Anweisung auf dem Slave
denselben Fehlercode verursacht. Wenn dieses Verhalten der
Fehlercodeauswertung nicht gewünscht ist, können einige oder
alle Fehler mit der Option
--slave-skip-errors
maskiert (d. h.
ignoriert) werden.
Wenn Sie transaktionssichere Tabellen aus
nichttransaktionssicheren Tabellen in einer
BEGIN
/COMMIT
-Sequenz
aktualisieren, sind die Änderungen im Binärlog unter
Umständen nicht synchron zu den Tabellenzuständen, wenn die
nichttransaktionssichere Tabelle aktualisiert wird, bevor die
Transaktion übergeben wird. Die Ursache hierfür ist, dass
die Transaktion erst dann in das Binärlog geschrieben wird,
wenn sie übergeben wird.
In Situationen, in denen Transaktionen Updates für transaktionssichere und nichttransaktionssichere Tabellen vermischen, ist die Reihenfolge der Anweisungen im Binärlog korrekt, und alle erforderlichen Anweisungen werden – auch bei einem Rollback – in das Binärlog geschrieben. Aktualisiert allerdings eine zweite Verbindung die nichttransaktionssichere Tabelle, bevor die Transaktion der ersten Verbindung abgeschlossen ist, dann kann die geloggte Anweisungsreihenfolge falsch sein, weil die Änderung der zweiten Verbindung unmittelbar nach ihrer Ausführung geschrieben wird – unabhängig von dem Zustand der Transaktion, die von der ersten Verbindung durchgeführt wurde.
Dies ist eine Übersetzung des MySQL-Referenzhandbuchs, das sich auf dev.mysql.com befindet. Das ursprüngliche Referenzhandbuch ist auf Englisch, und diese Übersetzung ist nicht notwendigerweise so aktuell wie die englische Ausgabe. Das vorliegende deutschsprachige Handbuch behandelt MySQL bis zur Version 5.1.