MySQL-Ring-Replikation

bitmuncher

Senior-Nerd
Folgende Situation: Ich habe 3 Datenbankserver. server1 ist Master für server2, server2 ist Master für server3 und Server3 ist Master für server1. Also eine einfache Ring-Replikation.

Das Problem ist nur, dass die Replikation zwar problemlos funktioniert, wenn die Datenbank frisch eingerichtet ist, aber... Wird eine Tabelle gelöscht, bekommen das beim ersten Mal auch alle Server mit. Erstellt man danach eine identische Tabelle (gleicher Name, gleiche Felder) nochmal, wird diese Tabelle aber nicht mehr auf den anderen Servern angelegt. Erstelle ich die Tabelle danach auf allen Servern per Hand, werden eingefügte Datensätze nicht mehr repliziert. Die Binlog-Position wird allerdings korrekt von 'show slave status' angezeigt. Lösche ich die Tabelle danach nochmal, bekomme ich beim 'show slave status' die Meldung "Error 'Unknown table 'test'' on query. Default database: 'test'. Query: 'drop table test'". 'log-slave-updates' ist aber aktiviert. Erst nach einer Neu-Einrichtung aller Datenbanken funktioniert die Replikation wieder. Restart der Slaves und erneutes Ausführen von 'change master...' reicht leider nicht aus.

Hat irgendwer eine Idee, woher diese Fehler kommen können und wie man die vermeiden kann? Bin für jeden Denkanstoss dankbar, da ich mittlerweile absolut im Dunkeln tappe nachdem ich Fehlerquellen wie asynchrone Zeit auf den Servern, Versionsunterschiede, Konfigurationsunterschiede usw. ausgeschlossen habe.

MySQL-Version: 5.0.45-linux-i686-icc-glibc23
Konfiguration aller Server wie folgt:

Code:
[client]

[mysqld]
datadir              = /usr/local/mysql/data
set-variable         = key_buffer=128M
set-variable         = max_allowed_packet=1M
set-variable         = table_cache=512
set-variable         = sort_buffer=2M
set-variable         = record_buffer=2M
set-variable         = thread_cache=4

log-bin              = /usr/local/mysql/data/toksta1.binlog
log-slave-updates
binlog-do-db         = chatprovider
binlog-do-db         = test

server-id            = 1

master-host          = 123.123.123.123
master-port          = 3306
master-user          = slave_user
master-password      = meinslavepasswort
master-connect-retry = 60

replicate-do-db      = chatprovider
replicate-do-db      = test

[safe_mysqld]
err-log              = /usr/local/mysql/data/mysqld.log

[mysqldump]
quick
max_allowed_packet   = 16M

[mysql]
no-auto-rehash

[isamchk]
key_buffer           = 20M
sort_buffer_size     = 20M
read_buffer          = 2M
write_buffer         = 2M

[myisamchk]
key_buffer           = 20M
sort_buffer_size     = 20M
read_buffer          = 2M
write_buffer         = 2M

[mysqlhotcopy]
interactive-timeout

Natürlich unterscheiden sich auf den einzelnen Servern die Master-Hosts, wobei die in der Konfiguration ja eh irrelevant sind, da ich 'change master to...' verwende, was dann ja in der master.info abgelegt wird.
 
Zwischendurch auf allen Maschinen von Hand erstellen muss in einer
Ring Replikation prinzipiell Fehler geben (zumindest wenn die Replikation funktioniert)
denn konzeptioniell darfst du, egal was, alles nur einmal machen darfst.

Lösche ich die Tabelle danach nochmal, bekomme ich beim 'show slave status' die Meldung "Error 'Unknown table 'test'' on query.

s.o. Ausser ich habe das falsch verstanden :)

Ich hatte ähnliche Probleme und nach einem halben Jahr nichts als ärger hab ich eine
solche Ring Replkation wieder abgebaut und durch eine master(2) -> slave (2) Konfiguration getauscht. Ringe sind einfach viel zu anfällig und machen zuviel Arbeit.

Wenn du allerdings rauskriegst wo es hakt würde mich das brennend interessieren ;)

Btw.: Ich hatte die Konfigurationen in den Config Dateien direkt drin.
 
Wenn ich das Prinzip richtig verstanden habe, dann soll diese Replikation Transaktionen auf allen Knoten erlauben - diese dann aber global verfügbar machen, korrekt?

Wenn Du die Tabelle löschst, melden die anderen beiden Knoten denn auch brav committed an den auslösenden Knoten? Hier würde ich ansetzen.

Klappt denn das neue anlegen eine Tabelle mit _anderem_ Namen? Wenn ja, könnte das auch ein bug (hashing oder so) sein.
 
@KlausSchiefer: Danke für den Hinweis, dass man alles nur einmal machen kann. Da liegt offenbar tatsächlich das Problem, denn taucht ein Query zweimal in den Binlogs auf (wie z.B. das 'create table'), wird es nur einmal auf den Slaves ausgeführt und das offenbar unabhängig von den Zeiten, wann das Query ausgeführt wurde. Wenn ich den Code des MySQL-Servers da richtig interpretiert habe, ist das notwendig um evtl. Race-Conditions zwischen 2 oder mehr Queries zu verhindern. Leider betrifft das auch nicht nur das Löschen und Wiederanlegen von Tabellen, sondern auch das Löschen und Wiedereinfügen von Datensätzen, die keine eindeutige ID haben. Sobald Datensätze geschrieben werden, die 100% identisch zu einem vormals geschriebenen Datensatz sind, tritt dieser "Fehler" auf.

Ich werde daher mal mit unseren Entwicklern absprechen, ob wir nicht evtl. doch besser ein Clustering nutzen (Problem dürfte da sein, dass ndbcluster-Tabellen keine Fulltext-Search unterstützen) oder vielleicht sogar eine einfache Master->Slave-Replikation ausreicht, so dass Lesezugriffe über localhost abgesetzt werden können, Schreibzugriffe aber prinzipiell auf einen einzigen Master gemacht werden müssen, den wir evtl. sogar noch von den Lesezugriffen befreien und dadurch die Last senken. Beim Clustering sehe ich halt das Problem des Management-Knotens, bei dessen Ausfall ein Restart des kompletten Clusters notwendig ist. Ich habe damit schon genug schlechte Erfahrungen gesammelt, weswegen ich ja diesmal zur Replikation tendiert habe.
 
Weil Timestamps zusätzliche Rechenleistung auf dem Server kosten, wenn auch minimal. Und leider kann ich auch nicht ausschliessen, dass ein Entwickler mal eine Tabelle löscht und sie danach neuanlegen will, wenn er z.B. eine grosse Tabelle schnell leer machen will/muss.
 
@bitmuncher

Es kommt natürlich auf die Grösse an ;) (vom netzwerk)
Ich habe meistens die Fälle von viel lesen und langen Querys und damit wirklich störenden locks gehabt und dann halt 1-2 Master mit jeweils 1-2 Slaves aufgebaut.
So hast du u.U. 4 Maschinen die einspringen können. Bei einem Ring muss nur eine Maschine ausfallen und du hast ein Problem.

Und leider verlangt replikation auch immer einer gewisse Disziplin der Entwickler, die man ja nicht unbedingt vorraussetzen kann ;)
 
Zurück
Oben