dedlfix: Zeichensatz-Problem

Beitrag lesen

Hi!

[..] und die Daten zwischen der beim Speichern und der zur Kommunikation konfigurierten Kodierung umkodiert, wenn beide unterschiedlich sind.

Das verstehe ich nicht so richtig. Wenn ich utf8-codierte Zeichen in der DB habe und ein DB-Handle soll mir die Zeichen da rausholen... also ich verstehe das nicht. Ein DB-Handle stellt mir die Verbindung zwischen PHP und DB her. Was hat das mit der Zeichenkoderung zu tun, die ich dem handle mitteilen muss?

Es geht hier speziell um MySQL (ab Version 4.1). Und MySQL legt Daten in den Feldern einer Tabelle in Kodierung X ab. Wenn ein Client sich mit einem MySQL-Server verbindet, und dieser Client die Kodierung Y zum Senden umd Empfangen von Daten verwenden möchte, dann kodiert MySQL die Daten in den Feldern mit der Kodierung X um in die Kodierung Y, damit der Client trotz der X-Kodierung des Feldes seine Daten Y-kodiert bekommen kann. Und umgekehrt in der Senderichtung.

Dieses Verhalten will man in aller Regel nicht haben, weil beim Umkodieren zwischen zwei Kodierungen prinzipbedingt Verluste auftreten können. Man bekommt es aber, wenn man nur die Felder vom Defaultwert abweichend konfiguriert, die Verbindungskodierung aber nicht. Und dann wundert man sich, wenn man X annimmt, aber aufgrund des ungeänderten Defaultwertes Y bekommt.

Wenn man alles richtig macht, ist der Ablauf wie folgt - mit einer kleinen Abschweifung vorab:

Es gibt eine Menge Konfigurationsoptionen und -variablen. Der Unterschied zwischen Option und Variable ist hier nicht weiter relevant. Einige dieser Variablen lassen sich jedenfalls individuell für die Session zwischen Client und Server umstellen. Es gibt dann neben dem globalen Wert den sessionspezifischen Wert. Man sieht das zum Beispiel im phpMyAdmin unter "Show MySQL system variables" auf der Startseite. Wenn keine Felder orange hinterlegt sind, kann man (ebenfalls auf der Startseite) mal den Wert "MySQL connection collation" umstellen. (Man macht sich dabei nichts grundlegendes kaputt, denn das ist ein session-individueller Wert für den PMA.) Nun sollten einige Werte mit einer zweiten Zeile "(Global value)" zu sehen sein. Der obere Wert ist der session-individuelle. Nach dem Test sollte man "MySQL connection collation" wieder zurückstellen (Vergessen, was es war? utf8_general_ci passt meistens).

Für die Zeichensatz/-kodierungsproblematik sind die Werte character_set_... relevant.

Ein Client sendet ein SQL-Statement, von dem der MySQL-Server annimmt, es sei gemäß character_set_client kodiert. (Innerhalb eines SQL-Statements können einzelne Werte anders kodiert sein, wenn man sie besonders kennzeichnet. Das braucht man im Normalfall aber nicht.) Das SQL-Statement wird umkodiert nach character_set_connection (außer den besonders gekennzeichneten Einzelwerten). Bis hier hin passiert das mit allen SQL-Statements, egal ob Daten gelesen oder geändert werden oder auch nicht. Die Ergebnisse, die in Richtung Client gesendet werden sollen, werden gemäß character_set_results kodiert.

Die drei Variablen character_set_client, character_set_connection und character_set_results lassen sich mit der MySQL-C-API-Funktion mysql_set_character_set() (oder einem Pendant in einer sprachspezifischen API (PHP: mysql(i)_set_charset())) oder einem "SET NAMES"-Statement einstellen. (SET CHARACTER SET sieht man auch gelegentlich, das arbeitet jedoch etwas anders, wie im nachfolgend verlinkten Kapitel nachgelesen werden kann.)

Soweit lässt sich das alles im Kapitel Character Set Support, speziell Connection Character Sets ... nachlesen. Nun fehlt aber noch der Teil wie Daten in und aus Feldern geschrieben und gelesen werden. Dazu konnte ich nicht explizit etwas im Handbuch finden. Meine Erfahrung, gesammelt und bestätigt auch durch einige Experimente, besagen, dass die Daten noch einmal umkodiert werden, dieses Mal von character_set_connection in die Feldkodierung. Und für den Rückweg braucht es nur noch eine Umkodierung des Ergebnissets nach character_set_results.

Das war eine Menge Umkodierungen. Idealerweise muss aber nichts umkodiert werden, wenn alle beteiligten Variablen und die Felder-Konfigurationen auf die gleiche Kodierung eingestellt wurden.

Neben dem "Character Set" gibt es auch noch den Begriff "Collation", der oft in unmittelbarer Nähe zu "Character Set" zu finden ist. Die Konfigurationsvariablenorgie ist für beides nahezu gleich. Collation hat aber zur Aufgabe Regeln für das Vergleichen von Zeichen (zum Sortieren beispielsweise) zu definieren. Für Probleme mit der Kodierung kann man den Collation-Wert unberücksichtigt lassen.

Lo!