Datenbank von latin1 (iso-8859-1) auf utf8 umstellen

Aus Wiki | modified eCommerce Shopsoftware
Zur Navigation springenZur Suche springen

Ein Wort vorweg[Bearbeiten]

Bei dieser Thematik darf man seinen Augen nicht trauen. Die zur Verfügung stehenden Werkzeuge haben eigene Intelligenz und konvertieren oftmals im Hintergrund auf den Zeichensatz, der ihnen richtig scheint. Sowohl Browser, als auch MySQL und etliche Texteditoren zeigen nicht in jedem Fall, was zu erwarten wäre, und oft nicht das, was real in der Datenbank steht. Soweit möglich, ist also zu prüfen, welcher Zeichensatz aktuell eingestellt ist.

Hier ist die reine Datenbankmigration mit den Bordmitteln der MySQL-Datenbank beschrieben.

Voraussetzungen[Bearbeiten]

MySQL-Installation Shell, DOS-Box, Commandline-Interface oder wie auch immer das gerade bei Euch heißt, im Zeichensatz utf8.

Prüfe Zeichensatz der Shell[Bearbeiten]

Linux: echo $LANG sollte de_DE.UTF-8 ergeben. Wenn nicht ist die Umgebungsvariable entsprechend zu setzen. Die Bezeichnung kann zwischen verschiedenen Distributionen variieren, das Prinzip ist gleich. Windows: chcp sollte 65001 ergeben. Andernfalls das Kommando chcp 65001 absetzen.

Prüfe Zeichensätze im MySQL-Interface[Bearbeiten]

show variables like '%char%'
+--------------------------+----------------------------+
| Variable_name            | Value                      | 
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

Wesentlich sind hier die Einträge character_set_client, character_set_connection und character_set_results. Wenn die Shell richtig eingestellt ist, sollte hier jeweils der Wert utf8 stehen, und dann wird auch das Dump-Kommando wie gewünscht exportieren und während des Exports die eigentliche Umsetzung der Zeichen vornehmen.

Export (und Konvertierung) per mysqldump[Bearbeiten]

mysqldump DATENBANKNAME > DATEINAME

Der so erzeugte Dump ist bereits nach utf8 konvertiert, enthält aber Angaben, die den ursprünglichen Zeichensatz beim Import wieder herstellen. Da wir das nicht wollen, müssen wir diese Angaben entfernen. Das kann durch Suchen und ersetzen im Dump geschehen. Da das eine einfache Textdatei ist, kann das im Texteditor erledigt werden, der gemeine Linuxer setzt dazu das Kommando sed ein. Das sollte auch in OS X enthalten sein, und es gibt auch Varianten für Windows.

cat DATEINAME | sed s'/DEFAULT CHARSET=.*;/DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;/g'  > DATEINAME_UTF8

Für alle, die sed nicht mögen gilt:

Im Normalfall reicht es, den String "DEFAULT CHARSET=latin1 COLLATE=latin1_german_ci" durch "DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci" zu ersetzen, wobei eventuell statt des hierzuland üblichen Zeichnensatzes latin1 und der Collation latin1_german_ci auch andere Werte vorliegen können.

Vorsicht Falle[Bearbeiten]

MySQL kann nicht nur pro Datenbank und Tabelle, sondern gar auf Feldebene den Zeichensatz explizit angeben. Man frage mich bitte nicht, wie das passieren kann, aber es kommt tatsächlich vor. Bevor wir also importieren, durchsuchen wir das Ergebnis noch einmal nach falschen Angaben und ersetzen diese entsprechend. Die Angaben pro Feld sollten ganz entfallen. In meinem Anwendungsfall stand da zum Beispiel:

CREATE TABLE `address_book` (
 `address_book_id` int(11) NOT NULL AUTO_INCREMENT,
 `customers_id` int(11) NOT NULL,
 `entry_gender` char(1) COLLATE latin1_german1_ci NOT NULL,
 `entry_company` varchar(64) COLLATE latin1_german1_ci DEFAULT NULL,

Suchen des Strings COLLATE latin1_german1_ci und ersetzen durch nichts ergibt das gewünschte Ergebnis.

cat DATEINAME_UTF8  | sed s'/COLLATE latin1_german1_ci//g' >  DATEINAME_UTF88

Import[Bearbeiten]

Vor dem Import empfehle ich die Umstellung der Default-Werte für die Datenbank. So werden neue Tabellen auch ohne Angabe eines Zeichensatzes gleich in utf8 angelegt.

mysql> alter database DATABASE_NAME character set utf8 collate utf8_general_ci;

Nun der eigentliche Import:

mysql DATABASE_NAME < DATEINAME_UTF88

Das war die ganz Hexerei in der Datenbank.

Im Shop[Bearbeiten]

Einige Kleinigkeiten sind noch im Shop zu ändern:

Sprachdateien[Bearbeiten]

In den Sprachdateien (/lang/SPRACHE/SPRACHE.php und /lang/SPRACHE/admin/SPRACHE.php) muss die Locale des Servers kontrolliert / eingestellt werden. Unten ein Beispiel aus der Version 2.0.0.0, hier muss nichts geändert werden:

@setlocale(LC_TIME, 'de_DE.UTF-8' ,'de_DE@euro', 'de_DE', 'de-DE', 'de', 'ge', 'de_DE.ISO_8859-1', 'German','de_DE.ISO_8859-15');

Ein weiteres Beispiel aus Version 1.06 sp 4, noch ohne utf8:

@setlocale(LC_TIME, 'de_DE@euro', 'de_DE', 'de-DE', 'de', 'ge', 'de_DE.ISO_8859-1', 'German','de_DE.ISO_8859-15');

Dazu sollte man wissen, dass die Funktion setlocale sich die korrespondierende Einstellung vom Server zieht. Deshalb stehen so viele verschiedene Einträge in der Zeile. Unter Linux kann die Umgebungsvariable LANG mit der Ausgabe von "echo $LANG" bzw von "locale -a" abgeglichen werden.

Testroutine dazu im Forum

Charset in den Spracheinstellungen[Bearbeiten]

(admin/Land/Steuer/Sprachen), und zwar für alle Sprachen gleichermaßen utf-8. Bitte auf den Bindestrich achten, HTML muss ihn haben, MySQL darf ihn nicht haben.

Konstante für die Serververbindung[Bearbeiten]

In /includes/configure.php

define('DB_SERVER_CHARSET','utf8');

Danach den Browser neu starten, sonst hängt die alte Einstellung noch drin und das Ergebnis sieht grausam aus.

Tipps für alte Shopversionen[Bearbeiten]

Die obige Anleitung betraf zunächst nur die Datenbank, Hier noch Tipps aus dem Forum:

Umstellung einer Version 1.05 mit Multishop