MySQL, Schreiben in mehrere Datenbanken und AUTO_INCREMENT


Bei einem Kunden haben wir neulich einige Datenbanken auf einen neuen Datenbankserver umgezogen. Da wir aus Latenzgründen jedoch nicht alle Anwendungen auf den neuen Server umstellen konnten (der neue Server befindet sich im Rechenzentrum eines anderen Providers), haben wir uns entschlossen, eine Kopie der Datenbanken auf dem bisherigen Datenbankserver zu belassen.

Nun stellte sich allerdings das Problem, dass wir irgendwie beide Datenbanken synchron halten mussten. Replikation war leider keine Option, da wir den besagten Server bereits mit einem Backup-Server replizierten. Auch das periodische ziehen eines Dumps kam nicht in Frage, da wir die Daten nach dem Schreiben sofort auf beiden Systemen benötigten.

Wir entschieden uns daher, die Pflegeanwendung in beide Datenbanken gleichzeitig schreiben zu lassen. Damit es zu keinen Problemen mit inkonsistenten Datenbeständen zwischen den beiden Servern kommt implementierten wir das Schreiben folgendermaßen:

Starte Transaktion auf Server 1
Starte Transaktion auf Server 2

For QUERY in QUERIES:
    Führe Query auf Server 1 aus
    Führe Query auf Server 2 aus

If !ERROR:
    Commite Transaktion auf Server 2
    Commite Transaktion auf Server 2

Else:
    Rolle beide Transaktionen zurück


In unseren Tests lief alles gut, das Transaktionshandling funktionierte. Selbst bei provozierten Fehlern verhielt sich alles so, wie erwartet.

Kurz nach der Installation der Anwendung beim Kunden traten jedoch Probleme auf mit einem Fall, den wir leider vollkommen übersehen hatten: Durch einen unglücklichen Umstand war es möglich, auf Server 1 ein Insert-Query auszuführen, das auf Server 2 fehl. Eigentlich sollte hier unser Transaktionshandling eingreifen und die Änderungen rückgängig machen.

So weit die Theorie. In der Praxis hat das Rollback zwar durchaus die Änderung rückgängig gemacht, hat allerdings das AUTO_INCREMENT Value nicht wieder dekrementiert. Dies bedeutete nun, dass das AUTO_INCREMENT auf Server 2 eins niedriger war als das auf Server 1, was dazu führte, das alle weiteren Updates fehlschlugen, da nun alle von unserer Tabelle abhängigen Foreign Keys schief standen.

Die rettende Idee kam von einem Kollegen: Nach dem ausführen des Insert Statements auf dem ersten Server lesen wir nun mit LAST_INSERT_ID() den Wert der AUTO_INCREMENT Spalte aus und fügen diese explizit in den Set Part des Statements, das wir auf dem zweitem Server ausführen, ein. Somit laufen die IDs nicht auseinander und unser Tag und die Applikation war gerettet.

1 Comment(s)

  1. Kommentar by Artus on 04.03.2008 18:02

    Da legen MySQL und der SQL Server bei den Auto-Increment-Werten im Falle eines Rollback identisches Verhalten an den Tag :-)

    (wäre auch schwierig bei mehreren parallel verlaufenden Transaktionen im Rollbackfall noch immer IDs ohne Lücken vergeben zu haben)

Comments RSS TrackBack Identifier URI

Hinterlasse einen Kommentar


I, Blog is proudly powered by WordPress and themed by Mukkamu