1211chef: umstellung mariadb, nun codierungsproblem

hi leute, ich war schon ewig nicht mehr aktiv hier.

mein serverbetreiber hat von mariadb 10.3 auf 10.6 ungestellt, und nun habe ich ein umlautproblem.

in meinen alten perlscripten lese ich sql daten ein und speichere sie auch, collation der textfelder stehen alle auf latin1_swedish_ci. hat bisher immer problemlos funktioniert, alle ausgaben und eingaben mit umlauten korrekt, aber seit der umstellung nicht mehr.

mein problem ist jetzt auch, liegt es an alten programmierfehlern meinerseits, oder hat mein serverbetreiber irgendeine einstellung falsch gesetzt?

da ich in perl einlese, kann es damit zusammenhängen?

ich will jetzt ungern im datenbestand rumpfuschen, eine spalte hab ich leider eh schon vernichtet weil ich versucht habe auf utf8mb4 umzustellen. war ein fehler leider.

im moment komme ich nicht weiter, und mein serverbetreiber sagt es liegt an mir ...

grüsse, gust

  1. 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
    1. @@Rolf B

      Der Standardzeichensatz "latin1_swedish_ci"

      Zeichensatz? Eine Collation ist doch mehr als das.

      Verwende den Latin1-Zeichensatz. Sortiere nach schwedischen Regeln und vergleiche ohne Beachtung von Groß- und Kleinschreibung.

      Eben.

      Das passt für Deutsch halbwegs.

      Werden im Schwedischen nicht Umlaute nach Z einsortiert? Da würde ich dann nicht von „passt halbwegs“ sprechen, sondern von: passt gar nicht.

      Solange Du in Perl nicht versuchst, einen solchen String zeichenweise (statt byteweise) zu verarbeiten, fällt das gar nicht auf.

      Bist du da mit der Verneinung und Zeichen und Bytes durcheinander gekommen?

      Einen solchen UTF-8 String

      So etwas gibt es nicht. Man kann vielleicht von einer UTF-8-Bytefolge (mind the non-gap!) sprechen.

      Ein String besteht aus Zeichen, diese sind aus einem Zeichensatz. UTF-8 ist kein solcher, sondern eine Zeichencodierung.

      Ich weiß nicht, wie weit Du Dich auf 100% UTF-8 einlassen kannst.

      Ich weiß, dass man sich 100%ig auf UTF-8 einlassen sollte. Und jetzt will der Mitleser 2.0 auch noch eine Begründung dafür! 😏

      🖖 Живіть довго і процвітайте

      --
      Ad astra per aspera
      1. Hallo Gunnar,

        Zeichensatz? Eine Collation ist doch mehr als das.

        Ja. Stimmt. Der Zeichensatz ist das vor dem ersten Unterstrich.

        Werden im Schwedischen nicht Umlaute nach Z einsortiert? Da würde ich dann nicht von „passt halbwegs“ sprechen, sondern von: passt gar nicht.

        Ups. Danke. Passt gar nicht.

        Solange Du in Perl nicht versuchst, einen solchen String zeichenweise (statt byteweise) zu verarbeiten, fällt das gar nicht auf.

        Bist du da mit der Verneinung und Zeichen und Bytes durcheinander gekommen?

        Ja. Hm. Scheißencodings. Ich hatte den Text mehrfach umgeändert. Gemeint hatte ich: Wenn man die Bytefolge eines latin1-codierten Strings als UTF-8 deutet und dann zeichenweise verarbeitet, geht's schief. Weil nur einzelne Bytes mit Wert > 127 da sind, und keine UTF-8 Sequenzen.

        Oje. Jetzt hab ich am Ende vermutlich mehr Durcheinander gemacht statt sortiert.

        Ich weiß nicht, wie weit Du Dich auf 100% UTF-8 einlassen kannst.

        Ich weiß, dass man sich 100%ig auf UTF-8 einlassen sollte.

        Weiß ich ja auch. Aber wenn man eine Tonne Latin1-Legacy hat, mag das anders aussehen.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. @@Rolf B

          Solange Du in Perl nicht versuchst, einen solchen String zeichenweise (statt byteweise) zu verarbeiten, fällt das gar nicht auf.

          Bist du da mit der Verneinung und Zeichen und Bytes durcheinander gekommen?

          Ja. Hm. Scheißencodings. Ich hatte den Text mehrfach umgeändert. Gemeint hatte ich: Wenn man die Bytefolge eines latin1-codierten Strings als UTF-8 deutet und dann zeichenweise verarbeitet, geht's schief. Weil nur einzelne Bytes mit Wert > 127 da sind, und keine UTF-8 Sequenzen.

          Oje. Jetzt hab ich am Ende vermutlich mehr Durcheinander gemacht statt sortiert.

          Ähm, ja. Hätte es nicht das getan:

          Solange Du in Perl nicht versuchst, einen solchen String byteweise (statt zeichenweise) zu verarbeiten, fällt das gar nicht auf.

          Ich weiß, dass man sich 100%ig auf UTF-8 einlassen sollte.

          Weiß ich ja auch. Aber wenn man eine Tonne Latin1-Legacy hat

          Dann hat man schon vor Jahren was falsch gemacht.

          mag das anders aussehen.

          Aber ja, manchmal mag es einfacher (das kann dann auch bedeuten: sinnvoller) sein, die Zeichencodierung abweichend von UTF-8 anzugeben anstatt den ganzen Datenbestand umzucodieren.

          🖖 Живіть довго і процвітайте

          --
          Ad astra per aspera
          1. Hallo Gunnar,

            die Zeichencodierung abweichend von UTF-8 anzugeben

            was man dann konsistent, konsequent und konzentriert tun muss

            Rolf

            --
            sumpsi - posui - obstruxi
            1. @@Rolf B

              die Zeichencodierung abweichend von UTF-8 anzugeben

              was man dann konsistent, konsequent und konzentriert tun muss

              Sollte das nicht für so ziemlich alles gelten, was man tut? 😉

              🖖 Живіть довго і процвітайте

              --
              Ad astra per aspera
    2. Hallo Rolf, habe es nun mit etlichen Kollationen versucht, das mistding speichert mir, egal was ich versuche, einfach keine Sonderzeichen mehr, und gibt auch keine mehr aus.

      Witzigerweise kann ich über phpMyAdmin direkt Daten ändern, und sie stehen dann auch richtig in der DB. Sobald ich aber in Perl die DBI connecte, daten schreibe oder lese, werden (und egal auf welche Kollation ich das DB feld eingestellt habe), keine Sonderzeichen mehr verarbeitet.

      Im Grunde kann das jetzt doch nur ein Problem sein, das in der Zusammenarbeit zwischen Perl (DBI connect) und mariaDB entsteht.

      Ich stochere im trüben rum und komme nicht weiter.

      Die Misere hat mit der Umstellung von mariaDB begonnen, scheint damit aber nicht wirklich was zu tun zu haben.

      Es würde also null bringen, wenn ich alles auf UTF8 umstelle, alle Daten umarbeite ... sobald ich über die DBI schnittstelle ein ü sende, steht da ein ? drin.

      Ich dreh am Rad.

      Grüsse

      1. Moin,

        Hallo Rolf, habe es nun mit etlichen Kollationen versucht, das mistding speichert mir, egal was ich versuche, einfach keine Sonderzeichen mehr, und gibt auch keine mehr aus.

        Witzigerweise kann ich über phpMyAdmin direkt Daten ändern, und sie stehen dann auch richtig in der DB. Sobald ich aber in Perl die DBI connecte, daten schreibe oder lese, werden (und egal auf welche Kollation ich das DB feld eingestellt habe), keine Sonderzeichen mehr verarbeitet.

        Im Grunde kann das jetzt doch nur ein Problem sein, das in der Zusammenarbeit zwischen Perl (DBI connect) und mariaDB entsteht.

        genau das meinte Rolf in seiner vorherigen Antwort:

        • Für die Verbindung zwischen DB-Server und Client (also dein Perl)
          • als Default im Server
          • als Default im Client
          • explizit bei der Verbindungsaufnahme

        Du musst in der Datenverbindung den charset explizit setzen oder als ersten Query SET NAMES utf8 ausführen. (Disclaimer: Ich kenne mich mit Perl DBI nicht so gut aus, bei mir funktioniert

        my $dbh = DBI->connect("dbi:mysql:$dbName", $sqlUser, $sqlPass);
        $dbh->do('SET NAMES utf8');
        

        )

        Viele Grüße
        Robert

        1. Du musst in der Datenverbindung den charset explizit setzen oder als ersten Query SET NAMES utf8 ausführen. (Disclaimer: Ich kenne mich mit Perl DBI nicht so gut aus, bei mir funktioniert

          my $dbh = DBI->connect("dbi:mysql:$dbName", $sqlUser, $sqlPass);
          $dbh->do('SET NAMES utf8');
          

          )

          Bei mir auch

      2. Hi there,

        Im Grunde kann das jetzt doch nur ein Problem sein, das in der Zusammenarbeit zwischen Perl (DBI connect) und mariaDB entsteht.

        Hast Du die Datei, die das Perl-Skript beinhaltet, auch als UFT-8 gespeichert?

        1. Im Grunde kann das jetzt doch nur ein Problem sein, das in der Zusammenarbeit zwischen Perl (DBI connect) und mariaDB entsteht.

          Hast Du die Datei, die das Perl-Skript beinhaltet, auch als UTF-8 gespeichert?

          Das dürfte AFAIR nur relevant sein, wenn man im Script hardcodierte Kandidaten verwendet?

          1. Hallo

            Im Grunde kann das jetzt doch nur ein Problem sein, das in der Zusammenarbeit zwischen Perl (DBI connect) und mariaDB entsteht.

            Hast Du die Datei, die das Perl-Skript beinhaltet, auch als UTF-8 gespeichert?

            Das dürfte AFAIR nur relevant sein, wenn man im Script hardcodierte Kandidaten verwendet?

            Zumindest in PHP ist es eine gern genommene Stolperfalle in Skripten, die Daten aus der Datenbank lesen und eine Ausgabe generieren. Da muss das Skript, die DB-Verbindung und die Ausgabe die selbe Kodierung benutzen. Es würde mich wundern, wenn das bei Perl-Skripten „so ganz anders“ ist.

            Tschö, Auge

            --
            „Habe ich mir das nur eingebildet, oder kann der kleine Hund wirklich sprechen?“ fragte Schnapper. „Er behauptet, nicht dazu imstande zu sein“ erwiderte Victor. Schnapper zögerte (…) „Nun …“ sagte er schließlich, „ich schätze, er muss es am besten wissen.“ Terry Prattchett, Voll im Bilde
  2. The very most simple approach for you would be to try the following. Directly after connecting:

    my $dbHandle = DBI->connect
    

    try this:

    
    $dbHandle->do("SET NAMES 'utf8'");
    

    Bzw. in Deinem Fall auch was Anderes, womöglich "latin-1":

    https://php-de.github.io/jumpto/mysql-and-utf8/

    Gunnar wird Dir gleich erklären, warum alles außer UTF-8 ganz schlimm ist und Du bitte Deinen Code umzubauen hast.

  3. hallo ihr lieben, ja ich lese interessiert mit, aber ich bin leider aus der coderei einige jahre raus und habe derzeit privat so viel um die ohren, dass ich jetzt nicht die zeit habe mich wieder ausreichend einzuarbeiten. vielleicht ändert sich das mal wieder, aber im moment nicht, weil mein haus abgebrannt ist und ich seit längerem nix anderes mache als mich um dieses unglück zu kümmern.

    ich weiss, es ist hier nicht gerne gesehen, die bitte auszusprechen nach dem motto -könnt ihr mir einfach nur kurz helfen dass es wieder läuft-. dafür bin ich schon zu lange hier.

    aber im moment bleibt mir nichts anderes übrig als euch darum zu bitten.

    also wie kann ich -strukturiert- vorgehen, um das bug für den moment abzustellen? wie gehe ich vor?

    kann mein anbieter da wirklich auch nichts auf die schnelle machen? was denkt ihr? er hat ja nur von 10.3 auf 10.6 umgestellt, und davor gab es nie ein problem dieser art. also was ist zwischen diesen beiden versionen anders? habe was gelesen von setzen eines alias, was aber irgendwie wohl nur utf8 betrifft? ich denke, er könnte wenn er wollte, aber er will sich nicht damit beschäftigen. er sagt halt auch nur es ist ein codierproblem.

    nach dem öffnen des db handles set names auf utf8 zu setzen bringt jedenfalls keinen unterschied.

    vielleicht liegt´s wieder mal an einer perl einstellung? wäre nicht das erste mal. aber daran kann ich von hier aus nicht zugreifen, und hätte sowieso auch nicht das wissen dafür.

    gruss, gust

    1. Hallo 1211chef,

      Mr. Bing Googlesby zeigt mir bei der Suche nach "differences mariadb 10.3 10.6" diese Stelle:

      https://support.hostpoint.ch/en/products/news/information-on-databases/upgrading-the-mariadb-version#hp-section2

      Vielleicht ändert utf8mb3 ja was. Oder utfmb4. Was Perl-Schalter anbetrifft, da habe ich keine Ahnung. Auch nicht was die von Perl erwartete Codierung bei der Kommunikation mit dem SQL Server angeht.

      Jedenfalls finde ich keine Info, dass sich die Default-Codierung für Clientverbindungen grundsätzlich geändert hätte.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. https://metacpan.org/pod/DBD::MariaDB

        Automatische Übersetzung:


        UNICODE-UNTERSTÜTZUNG

        Alle stringorientierten Variablentypen (char, varchar, text und ähnliche Typen) werden von DBD::MariaDB als Unicode-Strings gemäß dem Standard-Perl-Unicode-Modell dargestellt. Das bedeutet, dass Perl-Skalare Unicode-Codepunkte und keine UTF-8-Bytes enthalten. Intern verwendet DBD::MariaDB den utf8mb4Zeichensatz von MySQL für die Netzwerkkommunikation mit MariaDB- und MySQL-Servern. Es wandelt den Netzwerk-MySQL- utf8mb4Zeichensatz automatisch in die Unicode-Perl-Skalare um und umgekehrt.

        Der Zeichensatz von MySQL utf8mb4für die Netzwerkkommunikation wird durch MYSQL_SET_CHARSET_NAMEdie C-Bibliotheks-API libmariadb/libmysqlclient konfiguriert. Dies ist eine Voraussetzung für eine funktionierende Anführungszeichenmethode und einen emulierten clientseitigen Platzhalterersatz.

        Versuchen Sie nicht, den Netzwerkzeichensatz (z. B. per SQL-Befehl manuell) auf etwas anderes als UTF-8 zu ändern, da dies die zugrunde liegende C-Bibliothek verwirren würde und DBD::MariaDB sich schlecht verhalten würde (z. B. zu einer fehlerhaften/unsicheren Anführungszeichenmethode oder einer emulierten Clientseite SET NAMESführen würde). Platzhalterersatz).

        Die Verwendung eines Nicht-UTF-8-Zeichensatzes für eine Spalte, Tabelle oder Datenbank ist in Ordnung, da der MariaDB- oder MySQL-Server den Speicherzeichensatz automatisch in den vom Netzwerkprotokoll ( utf8mb4) verwendeten Zeichensatz umwandelt. Beachten Sie, dass DBD::MariaDB beim Herstellen einer Verbindung zum MariaDB- oder MySQL-Server einen SQL-Befehl aufruft, SET character_set_server = 'utf8mb4'um sicherzustellen, dass der Standardzeichensatz für neue Datenbanken UTF-8 ist. Beachten Sie, dass ein Standardzeichensatz für neue Tabellen aus einem Datenbankzeichensatz festgelegt wird.

        Falls der MySQL-Server den MySQL- utf8mb4Zeichensatz für ein Netzwerkprotokoll nicht unterstützt, würde DBD::MariaDB versuchen, den MySQL- utf8Zeichensatz zu verwenden, der eine Teilmenge der UTF-8-Codierung ist, die auf die 3-Byte-UTF-8-Sequenzen beschränkt ist. Die Unterstützung für den Zeichensatz von MySQL utf8mb4wurde in der MySQL-Serverversion 5.5.3 eingeführt.


        Ich dreh am Rad.

        Das bleibt so, wenn Du keine „Butter bei die Fische tust“.

        Denn für alles weitere müsste ich mehr sehen:

        • Verbindungsgaufbau, hierfür genutzter DBI-Treiber (noch mysql oder schon MariaDB?)
        • genutzte Perl-Module
        • Datenquelle (Eingabe?)
        • Ausgabe
        • wie das Perl-Skript gestartet wird (Umgebungsvariablen)
        • genutzte Perl-Module
        • e.t.c.

        Ich weiß nicht und sehe auch nicht, welchen Weg Deine Daten nehmen. Wie soll ich also helfen?

        Der Beginn einer wirklichem Hilfe bei Zeichensatzproblemen setzt anno 2024 immer voraus, dass die Bereitschaft besteht, ganze Projekte (Datenquellen, Speicher, Verarbveitung, Ein- und Ausgaben) auf modernes UTF8 umzustellen - statt zu versuchen, hier mit Kompatibilitätskrücken zu arbeiten, also zu „murksen“. Genau das macht - „***Überraschung!****“ - im Hinblick auf immer wieder aufscheinende Probleme letztendlich mehr Arbeit.

        1. Hi,


          UNICODE-UNTERSTÜTZUNG

          Alle stringorientierten Variablentypen (char, varchar, text und ähnliche Typen) werden von DBD::MariaDB als Unicode-Strings gemäß dem Standard-Perl-Unicode-Modell dargestellt. Das bedeutet, dass Perl-Skalare Unicode-Codepunkte und keine UTF-8-Bytes enthalten. Intern verwendet DBD::MariaDB den utf8mb4Zeichensatz von MySQL für die Netzwerkkommunikation mit MariaDB- und MySQL-Servern. Es wandelt den Netzwerk-MySQL- utf8mb4Zeichensatz automatisch in die Unicode-Perl-Skalare um und umgekehrt.

          Leider wird da schon im Original von Zeichensatz (Charset) geschrieben, wo es um's Encoding geht …

          Ich dreh am Rad.

          Am Glücksrad? Dann könnte man ein E wie Encoding kaufen ;-)

          cu,
          Andreas a/k/a MudGuard

          1. Leider wird da schon im Original von Zeichensatz (Charset) geschrieben

            Ist halt Perl…