06
Mär/10
0

MYSQL Datenbankmigration

Wer kennt das Problem nicht, man möchte eine MYSQL Datenbank von einem Server zum anderen migrieren? Doch wie geht man vor? Mit welcher Lösung kommt man ans Ziel, ohne manuell Umlaute zu korrigieren?

Die einfachste und wohl auch teuerste Lösung, wäre warscheindlich sich eine Navicat Vollversion zu kaufen, was einem pro Lizenz im professionellen Umfeld gut und gerne 130$ pro Lizenz kostet.

Aber auch mit Navicat seid Ihr vom ISO-8859-1 (besser bekannt als LATIN1) Wechsel auf UTF-8 nicht 100% gefeit. Richtig lustigs wird's aber, wenn ihr noch einen alten MYSQL 4.0 Server habt, der noch kein UTF-8 versteht, ihr in aber schon damit geflutet habt. Die Wahrscheinlichkeit ist gross, spätestens dann wenn ihr einigermassen aktuelle CMS, Blogsoftware usw. einsetzt.

Was tut Ihr jetzt?

mysqldump?

Der wird logischerweise davon ausgehen, dass Ihr noch LATIN 1 einsetzt, ist ja heute noch so in der Standardkonfiguration (ja das MYSQL Projekt hat die Globalisierung wohl verschlafen). Ihr bekommt mit Glück einigermassen sauberes UTF-8 zurück, welches spätestens nach iconv wieder glänzt. Oder ihr habt ein schier unlösbares encoding Chaos.

Auch Navicat korrigiert nicht alle Encodingprobleme, dh. auch hier bleiben noch Fehler.

Was genau machen wir jetzt?

Da meine PHP Skills normalerweise mit der Herausforderung besser werden, dachte ich an ein Datenbank-Migrations-Script.

Ihr Administratoren da draussen könnt euch aber sicher noch an den Tag erinnern, als Ihr in der Standart Konfiguration bei #bind-address 127.0.0.1 die # entfernt habt.

Unser Problem hat sich soeben vom Encodingproblem zu einem "ich komme gar nicht an meine Daten" Problem gewandelt.

Eine Art Tunnel muss her:

  • ssh2 Klasse von PHP (Extension) nutzen, die Anfrage auf dem Terminal machen, xml ausgeben, xml parsen... (habe ich alles mehr oder weniger zum laufen gebracht, ist aber sau lahm, sehr unzuverlässig, weil die Klasse nicht mit jeder PHP Version sauber kompiliert, es sollte ein UNIX Server sein, da die meisten Windows Server kein SSHD am laufen haben und last but not least: Habt Ihr einen SSH Zugang zum Server? Nicht? Dann geht es euch wie den meisten anderen ;)
  • ssh Tunnel per shell_exec("ssh -f -L 15000:127.0.0.1:3306 username@password -p 22} sleep 60 >> /tmp/logname.log") und dann per PDO Objekt weiter, auch hier braucht Ihr einen SSH Zugang zum Server. Den Ihr wahrscheinlich nicht habt.
  • HTTP Tunnel aufbauen, dh. auf dem Server auf dem die Datenbank läuft bzw. den Zugriff auf die Datenbank hat kommt ein kleines php File, welches die Datenbankabfrage als $_POST Request bekommt und als JSON zurück gibt. Die ganze Logik, dh. die Verarbeitung kann sein, wo immer man es wünscht. Der grösste Nachteil ist sicherlich die Sicherheit, weil sowohl die Anfrage als auch die Antwort in Klartext verläuft.

Es gibt sicherlich noch andere Möglichkeiten, aber ich bin bei der letzteren gelandet, da sie zuverlässig und vorallem vielseitig einsetzbar ist.

Ok, da war doch noch ein Encodingproblem oder?

Viele von euch kennen wahrscheinlich die Funktion utf8_encode(). Kennt Ihr den grössen Nachteil dieser Funktion? Sie geht nur, wenn sauberes LATIN1 daher kommt. utf8_encode() auf ein UTF8 String ruiniert euch eure Daten.

Ich habe desshalb in meine Tunnelimplementation noch eine Funktion eingebaut, welche mir ziemlich zuverlässig auch Mischencoding korrigiert:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
<?php
 
function encode_to_utf8 ($input) {
$output = $input;
if($encoding == get_encoding($input)) {
$output = iconv($encoding, "UTF-8", $output);
}
return($output);
}
 
function get_encoding ($input) {
$encondings = array("ASCII", "UTF-8", "ISO-8859-1");
$input_md5 = md5($input);
foreach($encondings as $enconding) {
$sample = iconv($enconding, $enconding, $input);
if(md5($sample) == $input_md5) {
return($enconding);
}
}
return(false);
}
 
function recursive_encode_to_utf8 ($array) {
if(is_array($array)) {
foreach($array as $key => $value) {
if(is_array($value)) {
$tmparray[$key] = recursive_encode_to_utf8($value);
}
else {
$tmparray[$key] = encode_to_utf8($value);
}
}
return($tmparray);
}
else {
return(encode_to_utf8($array));
}
}

Downloads in der Reihenfolge der Liste (keines dieser Scripte bittet eine Komplettlösung, sodern sie beruhen auf meinen Erfahrungen. Sie stehen alle unter der LGPL):

Zurück

Einen Kommentar schreiben