Da wollte ich also neulich dringend INSERT ... IF EXISTS UPDATE und habe mein MySQL auf diesem Server durch ein neueres getauscht. Dafür gibt es recht ausführliche
Anweisungen. In den Anweisungen steht auch der Satz "MySQL generally recommends that you dump and reload your tables from any previous version to upgrade to 5.0". Den habe ich leider übersehen. Eigentlich sollte das in großen roten Buchstaben ganz oben stehen.
Das erste, das nicht mehr ging, waren die MySQL-eigenen Tabellen, sprich auch die mit den Zugangsdaten, so dass ich erstmal gar nicht mehr auf die Datenbank zugreifen konnte. An der Stelle habe ich mir überlegt, ob ich einfach das Vollbackup einspielen soll, mich aber doch dagegen entschieden. Backup einspielen ist verhältnismäßig langweilig. Man tippt ein paar Befehle und dann läuft alles wieder. Nein, jetzt wo das MySQL so schön verhunzt war, wollte ich das lieber zu Fuß machen.
Also zurück zu den nicht funktionierenden User-Tabellen. Hätte ich mal besser auf die Ausgabe von
mysql_upgrade geachtet. Das Problem lies sich teilweise mit einem manuellen Aufruf von
mysql_fix_privilege_tables beheben. Danach waren die Tabellen zwar lesbar, aber die Passworthashes abgeschnitten. Gut,
mysqld --skip-grant-tables lässt ja auch Zugriff ohne Passwort zu, also erstmal so die MySQL-Datenbank gefixt und dann wieder normal hochgefahren. Läuft.
An dieser Stelle habe ich gelernt, dass
MySQL 5 Zeichensätze kann. Man kann in der Konfigurationsdatei einen Default einstellen. Da ich UTF-8-Daten in der Datenbank habe, habe ich also UTF-8 eingestellt. Okay, MySQL mag meine UTF-8-Daten auch, denkt aber jetzt, dass die CHAR- und VARCHAR-Spalten alle nur noch ungefähr ein Drittel so lang sind wie sie eigentlich waren, weil Unicode mehr Platz braucht als Latin1. An dieser Stelle habe ich mir überlegt, ob ich einfach das Backup einspielen soll... aber wieder mit dem selben Schluss. Schließlich war die hauptsächlich davon betroffene Datenbank die von Serendipity, der Blog-Software, die ich verwende - und da wollte ich schon lange mal die Spalte für die Absender-IP-Adresse bei Kommentaren breiter machen, weil IPv6-Adressen immer abgeschnitten wurden. Also Serendipity was dieses Problem angeht gefixt und es läuft wieder.
Heute sagt mir Sibylle dann, dass bei einigen älteren Einträgen in meinem Blog Teile abgeschnitten sind. Da der Text der Einträge in TEXT-Spalten steht, sollte er aber nicht von dem eben beschriebenen Problem betroffen sein, denn TEXT-Spalten haben eine maximale Größe, die weit über das heraus geht, was der typische männliche Computerfreak an Meinungen äußert. Da ich absolut keine Lust hatte, den ganzen Text nochmal zu tippen, habe ich mir an dieser Stelle gefragt, ob ich nicht einfach nur das Vollbackup einspielen soll, mich dann aber doch dagegen entschieden und es mit dem binlog probiert. Das binlog ist bei MySQL ein Logfile, in dem alle Statements auftauchen, die jemals ausgeführt wurden. Komplett mit Timestamp und allem, was man so braucht. Auslesen kann man sie mit dem Tool
mysqlbinlog. Also ich ein
mysqlbinlog -dserendipity /var/lib/mysql/*-bin* | grep 'INSERT INTO .blog_entries' und festgestellt, dass im Binlog überraschenderweise der komplette Inhalt vorhanden war.
Also habe ich die Ausgabe von mysqlbinlog benutzt, um die Tabelle mit den Einträgen wieder aufzufüllen. Gut, jetzt war schon mal wieder mehr Text im Blog. Aber immer noch nicht alles. Komisch, denn mysqlbinlog kennt den
vollständigen Inhalt. Jetzt komme ich auch dazu, warum es mich überrascht hat, dass überhaupt der Inhalt im Binlog zu finden war. Das Binlog ist nämlich erst ab MySQL 5 das hauptsächliche Logfile-Format. Irgendwie hatte ich auf diesem Rechner versäumt, es vorher schon zu aktivieren. Offenbar wurde es dann während dem Upgrade aus den alten Logfiles oder aus purer Magie erzeugt. Kurz gesagt, entweder gibt es da Differenzen zwischen MySQL 4 und MySQL 5 bezüglich UTF-8 oder MySQL 5 ist merkwürdig, denn die Blog-Einträge endeten immer an Stellen vor sehr seltsam aussehenden Zeichenfolgen. Jetzt weiß ich ja, dass UTF-8
auch seltsam aussieht. Irgendwann ist mir dann aufgefallen, dass die seltsamen Zeichenfolgen nach den Abbruchstellen ganz andere sind als die seltsamen Zeichenfolgen vor diesen Stellen, auch wenn sie für das selbe Zeichen stehen. Tatsächlich waren da, inmitten von völlig korrektem UTF-8-Text, auch Sequenzen eingestreut, die kein UTF-8 waren und an denen sich MySQL offenbar verschluckt.
Nachdem ich diese aus der Ausgabe von mysqlbinlog per Suchen-Ersetzen in richtiges UTF-8 ersetzt habe und den Rest per Hand korrigiert habe, scheinen die Probleme, was Serendipity angeht, jetzt wohl auch behoben zu sein. Das nächste Mal nehme ich aber vielleicht doch lieber das Backup, das ich ja mittlerweile auch recht zuverlässig zuhause
spiegeln kann und nicht erst von einem FTP ziehen und entschlüsseln muss...