MySQL Upgrade van 4.0 -> 4.1

|

Vandaag werd de MySQL server geupgrade naar MySQL4.1. Deze versie van MySQL bevat enkele leuke nieuwigheden:

  • Ondersteuning voor subqueries
  • Ondersteuning voor UTF8

Sommige webapplicaties kunnen hierdoor niet meer correct functioneren.

Hieronder vinden jullie een lijstje van programma's waarvan de Upgrade van MySQL 4.0 naar 4.1 problemen kan leveren en hoe u deze kunt oplossen:

  • Drupal (met dank aan Steven Wittens)
    Symptomen:
    je krijgt foutmeldingen omtrent "collation errors" en alle niet-ASCII karakters op je site (vb letters met accenten) zijn vervangen door een of meer rommelkarakters.

    Oplossing:

    Omdat MySQL 4.0 geen Unicode/UTF-8 ondersteunde, gebruikte Drupal voor die versie Latin1 (de West Europese karakterset/encodering) voor de database tabellen, maar stuurde er in werkelijkheid UTF-8 data naartoe.

    Het is ook zeer belangrijk dat dit zo snel mogelijk opgelost wordt, want alle data die nà de upgrade in de database wordt gesavet wordt volledig anders behandeld. Een database met zulke gemengde inhoud kan je onmogelijk fixen zonder manueel te moeten gaan corrigeren.

    Er zijn twee oplossingsmethodes gegevens onderaan. De kortste is de 2de oplossing.

    Omdat Latin1 encodering voor iedere byte een karakter heeft, werd de UTF-8 bytestream zonder enige problemen opgeslagen in de database, en op identieke wijze teruggegeven aan Drupal. MySQL had gewoon een ander idee van wat die data voorstelde, maar dit gaf algemeen gezien geen problemen.

    Vanaf MySQL 4.1 echter is er wel ondersteuning voor UTF-8 en is MySQL veel slimmer met encoderingen gaan omspringen. Het resultaat is dat bovenstaande hack totaal niet meer werkt (en ook volledig onnodig is). Nu, Drupal is slim genoeg om de juiste encodering te gebruiken voor de juiste MySQL versie, maar kan helemaal niet zien als je je MySQL geüpgradet hebt.

    Het probleem is: de tabellen bevatten al UTF-8 data, maar MySQL denkt nog steeds dat het Latin1 data is. Als Drupal dus zegt "geef mij UTF-8 data", dan gaat MySQL 4.1 een conversie toepassen van Latin1 naar UTF-8, waardoor alle niet-ascii karakters verkeerd getoond worden. Omgekeerd gaat ook alle UTF-8 die Drupal stuurt omgezet worden naar Latin1, waardoor alle niet-Latin1 karakters (vb: euro-teken, em-dash, ronde aanhalingstekens, ...) vervangen worden door een vraagteken.

    Je kan dit echter niet oplossen door te tabellen te converteren naar UTF-8 (met "ALTER TABLE foo CHANGE CHARACTER SET" ofzo), want in dat geval gaat MySQL de onderliggende data zélf aanpassen. En dat wil je dus net niet. Dit was de fix die jullie aanraadden. Gelukkig was dit enkel voor de accesslog tabel, die enkel IP adressen en URLs bevat (dus alleen ASCII karakters), dus er is geen probleem voor gebruikers die deze 'fix' al toegepast hebben.

    Oplossing 1

    Met de volgende stappen kan je het probleem oplossen. We gaan er vanuit dat er enkel Drupal-tabellen in de database zitten:

    1) Doe een volledige database dump via phpmyadmin. Vink "DROP TABLE" en "IF EXISTS" aan, zodat je gemakkelijk kan her-importeren.

    2) Open de dump in een teksteditor, en vervang de tekst "DEFAULT CHARSET=latin1" door "DEFAULT CHARSET=utf8" onder iedere tabeldefinitie. Save dit als een nieuw bestand, zodat je in geval van problemen steeds je oude database nog hebt.

    Let op! Sommige teksteditors ondersteunen Unicode niet volledig en kunnen de dump zelf ook beschadigen. Op Windows is het aan te raden Notepad2 te gebruiken (opensource/gratis).

    3) Upload de nieuwe dump terug naar phpMyAdmin. De data wordt op identieke wijze ingevoegd, maar MySQL weet nu dat het de onderliggende bytes moet interpreteren als UTF-8.

    Oplossing 2

    In principe kan je dit ook via de shell doen op één van onze servers (wop of pec), met de dit scriptje of de volgende commando's:

    mysqldump -u USER -pPASSWORD DATABASE -h mysql.ulyssis.org --add-drop-table > dump.corrupt.mysql
    cat dump.corrupt.mysql | sed s/DEFAULT\ CHARSET=latin1/DEFAULT\ CHARSET=utf8/ > dump.fixed.mysql
    mysql -u USER -pPASSWORD DATABASE -h mysql.ulyssis.org -f --default-character-set=utf8 < dump.fixed.mysql