Rolf B: umstellung mariadb, nun codierungsproblem

Beitrag lesen

Hallo 1211chef,

und mein serverbetreiber sagt es liegt an mir ...

das tun sie immer, bis man ihnen klipp und klar das Gegenteil beweist...

Beim Datenbankgeschäft gibt es eine ganze Menge stellen, wo eine Codierung festgelegt werden kann.

  • In MySQL / MariaDB

    • auf Spaltenebene
    • auf Tabellenebene
  • Für die Verbindung zwischen DB-Server und Client (also dein Perl)

    • als Default im Server
    • als Default im Client
    • explizit bei der Verbindungsaufnahme
  • Für die Verbindung zwischen Client und Browser

    • per HTTP Header
    • per meta charset Angabe

Leider verstrickt man sich sehr gerne dabei, das alles richtig zu machen. Gemeinerweise fällt es oft genug auch gar nicht auf. Bis man die Codierung wechseln möchte. Deswegen ist das heutige Credo auch: Nimm UTF-8. Immer und überall. Perl möchte dabei helfen, wenn ich das richtig verstanden habe, die Frage ist nur, ob Du diese Hilfe auch nutzt oder ob dein Perl-Code älter ist als diese Hilfen. Dabei kann ich Dich aber nicht unterstützen, meine Perl-Kenntnisse sind so gut wie nicht existent.

Der Standardzeichensatz "latin1_swedish_ci" von MYSQL/MariaDB bedeutet: Verwende den Latin1-Zeichensatz. Sortiere nach schwedischen Regeln und vergleiche ohne Beachtung von Groß- und Kleinschreibung. Das passt für Deutsch halbwegs. "latin1_german1_ci" wäre besser (DIN-Sortierung), "latin1_german2_ci" wäre Telefonbuchsortierung.

Mit latin1 bist Du auf die Zeichen des Latin1-Zeichensatzes (Codepage 1252) limitiert, und jedes Zeichen wird in der DB in einem Byte gespeichert. Dadurch ist dieser Zeichensatz speicherökonomisch. Aber alles, was hier nicht drin ist, kannst Du nicht speichern. Oder schlimmer noch: du speicherst es falsch. Und das scheint bei Dir passiert zu sein.

Denn ein Browser operiert per Default mit Unicode und codiert die Daten mit UTF-8. Heißt: Alles, was nicht im ASCII-Zeichensatz ist (Codepoint < 128), wird mit zwei oder mehr Bytes codiert. Solange Du in Perl nicht versuchst, einen solchen String zeichenweise (statt byteweise) zu verarbeiten, fällt das gar nicht auf. Einen solchen UTF-8 String kannst Du auch in einer latin1-Spalte der DB speichern, und dann ist das Unglück vorprogrammiert.

Natürlich kannst Du das in Perl auch vermeiden; du kannst dem Browser sagen, dass du eine Latin1-Codierung willst (ISO8859-Familie). Das SOLL man zwar nicht und der HTML Standard sagt "Außer UTF-8 gibt's nichts", aber die HTML Wiese ist längst nicht so grün, wie die Spec es möchte, und in der Welt der Browser blüht noch reichlich Unkraut. Mit einem erzwungenen ISO8859-Charset bekommst Du deine Umlaute nicht als UTF-8 Sequenz, sondern als Latin1-Bytes.

Es gibt noch eine zweite Charset-Vereinbarung, nämlich die zwischen Perl und dem SQL Server. Dafür gibt's Defaults, und man kann das Charset auch bei der Verbindungsaufnahme festlegen. Wie Perl das macht, dazu kann ich nichts sagen. Aus Serversicht gibt's sieben verschiedene Character Set Einstellungen, jede davon ist an unterschiedlichen Stellen des langen Wegs vom Client zur Serverfestplatte relevant und ich beneide die Programmierer bei MariaDB überhaupt nicht um diese Vielfalt. Ich glaube, bis die das im Griff hatten, mussten sie täglich mehrere Eimer voll Erbrochenem aus dem Büro bringen.

Wenn Du mit einer Charset-Änderung deine Daten geschrottet hast, dann KANN es sein, dass sie falsch gespeichert wurden, also als UTF-8 String in einer Latin1-Spalte. In dem Fall solltest Du erstmal zurückkonvertieren und auf der Beste hoffen. Und dann solltest Du prüfen, wie der Zeichensatz der Perl-SQL Verbindung ist. Da könnte sich beim Hoster etwas geändert haben.

Ich weiß nicht, wie weit Du Dich auf 100% UTF-8 einlassen kannst. Dein Perl-Code könnte damit Probleme bekommen. Aber das ist lösbar, ganz bestimmt.

Das ist jetzt vermutlich kein Patentrezept für dein Problem. Ich fürchte, das gibt's auch nicht. Aber ich hoffe, ich konnte Dir zumindest die möglichen Ursachen aufzeigen. Zeichencodierung und deren Wechsel ist leider ein bösartiges Problem.

Rolf

--
sumpsi - posui - obstruxi