Robert R.: MySQL 5.5, Information_Schema, utf-8

Liebe Mitdenker,
liebe Wissende,
liebe Neugierige,

ja!

Beim Arbeiten mit dem Information_Schema bin ich auf eine Frage gestoßen.
Bei bei einer varchar-Spalte mit Standardlänge (50) sind die Angaben wie folgt:

  
CHARACTER_MAXIMUM_LENGTH     50  
CHARACTER_OCTET_LENGHT      150  
CHARACTER_SET_NAME         utf8  
  

Wie passt das zusammen.
UTF-8 benötigt doch eigentlich vier Bytes pro Zeichen:
http://de.wikipedia.org/wiki/UTF-8

Spielt MySQL hier Statistik-Roulette? Das würde zwar für übliche europäische Texte reichen, aber was ist, wenn jemand wirklich nur Zeichen mit vier Oktetts benutzt? Wird der String dann abgeschnitten?

Spirituelle Grüße
Euer Robert

--
Möge der Forumsgeist wiederbelebt werden!
  1. Liebe Mitdenker,
    liebe Wissende,
    liebe Neugierige,

    ja!

    gleich noch eine Anschlussfrage:

    Wo versteckt sich das delete-Recht für Zeilen in ein einer Tabelle. Auf die Abfrage

      
    select * from information_schema.columns where table_name='test';  
      
    
    

    bekomme ich in der Rechte Spalte nur die Antwort:

      
    PRIVILEGES          select,insert,update,references  
      
    
    

    Das ist zwar plausibel, dass hier das delete-Recht nicht aufgeführt wird, da man nur ganze Zeilen löschen kann. Aber was muss ich aus dem Information_Schema abfragen um festzustellen, ob der User in der Tabelle löschen darf (er darf es hier!)?

    Das obere Abfrageergebnis bezieht sich allerdings auch nur auf den aktuellen User.
    Wie müsste(n) die Abfrage(n) an das Information_Schema lauten, um für einen x-beliebigen User die Rechte auf eine Tabelle feststellen zu können?

    Spirituelle Grüße
    Euer Robert

    --
    Möge der Forumsgeist wiederbelebt werden!
    1. Tach!

      Wo versteckt sich das delete-Recht für Zeilen in ein einer Tabelle. Auf die Abfrage

      Wenn ich mir die (Pseudo-)Tabellen der (Pseudo-)Datenbank information_schema anschaue, sehe ich da nur eine mit dem Namen SCHEMA_PRIVILEGES, die einigermaßen so klingt, als ob sie zielführend wäre, wärend alle anderen wie Sackgassen aussehen oder sind.

      Das obere Abfrageergebnis bezieht sich allerdings auch nur auf den aktuellen User.
      Wie müsste(n) die Abfrage(n) an das Information_Schema lauten, um für einen x-beliebigen User die Rechte auf eine Tabelle feststellen zu können?

      Es sieht mir nicht so aus, als ob Information_Schema andere Informationen als die für den aktuellen Nutzer relevanten liefern kann. Befrag doch mal die Tabellen in der (echten) Datenbank namens mysql.

      dedlfix.

      1. Liebe Mitdenker,
        liebe Wissende,
        liebe Neugierige,

        ja!

        Wo versteckt sich das delete-Recht für Zeilen in ein einer Tabelle. Auf die Abfrage

        Wenn ich mir die (Pseudo-)Tabellen der (Pseudo-)Datenbank information_schema anschaue, sehe ich da nur eine mit dem Namen SCHEMA_PRIVILEGES, die einigermaßen so klingt, als ob sie zielführend wäre, wärend alle anderen wie Sackgassen aussehen oder sind.

        Das obere Abfrageergebnis bezieht sich allerdings auch nur auf den aktuellen User.
        Wie müsste(n) die Abfrage(n) an das Information_Schema lauten, um für einen x-beliebigen User die Rechte auf eine Tabelle feststellen zu können?

        Es sieht mir nicht so aus, als ob Information_Schema andere Informationen als die für den aktuellen Nutzer relevanten liefern kann. Befrag doch mal die Tabellen in der (echten) Datenbank namens mysql.

        Ich glaube, dass ich den Mechanismus einigermaßen verstanden habe. Ich habe vier Ebenen gefunden:

        information_schema.user_privileges             allgemeine Userrechte für alle Datenbanken
        information_schema.schema_privileges           allgemeine übergeordnete Rechte pro Datenbank
        information_schema.table_privileges            Rechte auf Tabellenebene
        information_schema.column_privileges           Rechte auf Spaltenebene

        Das funktioniert wohl immer noch so, wie früher, nur dass die in der MySQL.mysql-DB festgelegten Rechte nun in das virtuelle information_schema geladen werden.

        Es gelten die Übergeordneten Rechte, solange keine untergeordneten für das OBJEKT+USER vorhanden sind. Sowie eine Stufe tiefer Rechte auftauchen, fallen alle vorher erteilten für das Objekt+User weg und es gelten nur noch die in der Stufe eingetragenen Das setzt sich so fort, bis ans Ende.

        Ich werde mal ausprobieren, welche Abfragen welcher User tätigen darf und welche Ergebnisse ihm angezeigt werden. Vermutlich werden die gefiltert.

        Spirituelle Grüße
        Euer Robert

        --
        Möge der Forumsgeist wiederbelebt werden!
        1. Tach!

          Wo versteckt sich das delete-Recht für Zeilen in ein einer Tabelle. Auf die Abfrage

          Wenn ich mir die (Pseudo-)Tabellen der (Pseudo-)Datenbank information_schema anschaue, sehe ich da nur eine mit dem Namen SCHEMA_PRIVILEGES, die einigermaßen so klingt, als ob sie zielführend wäre, wärend alle anderen wie Sackgassen aussehen oder sind.

          Mein phpMyAdmin hat mir einen Streich gespielt. Der hat die Tabellen auf zwei Seiten aufgeteilt und ich hab nur die erste bemerkt. Es gibt also noch mehr Privilegien-Tabellen und du hattest sie gefunden.

          dedlfix.

          1. Liebe Mitdenker,
            liebe Wissende,
            liebe Neugierige,

            ja!

            Tach!

            Wo versteckt sich das delete-Recht für Zeilen in ein einer Tabelle. Auf die Abfrage

            Wenn ich mir die (Pseudo-)Tabellen der (Pseudo-)Datenbank information_schema anschaue, sehe ich da nur eine mit dem Namen SCHEMA_PRIVILEGES, die einigermaßen so klingt, als ob sie zielführend wäre, wärend alle anderen wie Sackgassen aussehen oder sind.

            Mein phpMyAdmin hat mir einen Streich gespielt. Der hat die Tabellen auf zwei Seiten aufgeteilt und ich hab nur die erste bemerkt. Es gibt also noch mehr Privilegien-Tabellen und du hattest sie gefunden.

            Ja. Mit Heidi.
            Man muss erstmal prokeln, um einen Einstieg ins Information Schema zu finden. Das ging dann am besten über

              
            Select * from information_schema.tables;  
              
            
            

            Spirituelle Grüße
            Euer Robert

            --
            Möge der Forumsgeist wiederbelebt werden!
  2. hi,

    Charset, Collation muss stimmen und das Programm muss mit MySQL per UTF-8 kommunizieren (SET NAMES ...), dann passt alles rein.

    Zur Demo hab eich mal eine Tabelle angelegt:

      
    CREATE TABLE `test` (  
      `id` int(11) NOT NULL AUTO_INCREMENT,  
      `text` varchar(10) COLLATE utf8_unicode_ci DEFAULT '',  
      `datum` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,  
      PRIMARY KEY (`id`)  
    ) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci  
    
    

    Anstelle "set names ..." gibt es in Perl ein spezielles Attribute fürn Connect:

      
    # Kommunikation per UTF-8  
    my $dbh =  DBI->connect(  
        "DBI:mysql:myweb:localhost:3306",  
        '', '',  
        {RaiseError => 1, PrintError => 0, mysql_enable_utf8 => 1}  
    );  
      
    $dbh->do('truncate test');  
    $dbh->do( qq(insert into test(text)values('1234567€€€')) );  
      
    my $s = $dbh->selectrow_array(qq(select text from test));  
      
    use bytes; # binmode STDOUT  
    print $s; # 1234567€€€  
      
    
    

    Und siehe da, die drei EUROs passen rein, macht zusammen 10 Zeichen, wie vereinbart. Ohne Attribute (mysql_enable_utf8 => 1) meldet der Treiber einen Fehler: String ist zu lang.

    MfG

    1. Liebe Mitdenker,
      liebe Wissende,
      liebe Neugierige,

      ja!

      Charset, Collation muss stimmen und das Programm muss mit MySQL per UTF-8 kommunizieren (SET NAMES ...), dann passt alles rein.

      Was hat die Collation mit dem Speicherplatzbedarf des Feldes zu tun?
      Ich benutze immer http://php.net/manual/en/mysqli.set-charset.php

      Was ist an 'set names' besser, als an der PHP-Funktion mysqli_set_charset()?

      Warum heißt der Spaltentyp 'varchar'? Hat das im Gegensatz zu 'char' vielleicht 'was zu bedeuten? Ich werde nicht ganz schlau aus dem Handbuch:
      http://dev.mysql.com/doc/refman/5.5/en/char.html
      Wird varchar nun auch abgeschnitten, oder nicht?

      Dein Versuch hinkt allerdings. Du müsstest mal 9 (oder 10?) Zeichen einfügen, die jedes vier Oktetts benötigen. Wenn ich das richtig verstehe, dann passen (zumindest bei Char(10)) nur 7 Zeichen rein in die Spalte. Der effektive Speicherbedarf dafür müsste dann 29 Bytes betragen (eins für die Länge). Aber das Längenbyte wird bei der Angabe der Länge vermutlich nicht mitgezählt, sondern ist nur an der oberen Grenze zu beachten, oder? Eine Char-Spalte kann dann maximal 255 Zeichen haben?

      Spirituelle Grüße
      Euer Robert

      --
      Möge der Forumsgeist wiederbelebt werden!
      1. Tach!

        Was hat die Collation mit dem Speicherplatzbedarf des Feldes zu tun?

        Nichts.

        Ich benutze immer http://php.net/manual/en/mysqli.set-charset.php
        Was ist an 'set names' besser, als an der PHP-Funktion mysqli_set_charset()?

        Nichts. Es macht sogar weniger. Aber das ist für ASCII, alle ISO-8859-... und UTF-8 nicht weiter relevant.
        Konkret stellt SET NAMES nur die Schnittstelle für die aktuelle Verbindung im Server um. mysqli_set_charset() stellt auch noch die Client-API um, so dass Funktionen wie mysqli_real_escape_string() die Zeichenkodierung ebenfalls berücksichtigen können. Da aber alle dafür relevanten Zeichen eineindeutige Bytewerte im ASCII-Bereich haben, fällt das nicht weiter ins Gewicht. Bei einigen asiatischen Kodierungen kann es aber Probleme geben, weil diese auch Bytes < 0x80 für Kombinationen verwenden und es dann andere Zeichen sind. Aber, wie gesagt, für uns nicht weiter relevant.

        Warum heißt der Spaltentyp 'varchar'? Hat das im Gegensatz zu 'char' vielleicht 'was zu bedeuten? Ich werde nicht ganz schlau aus dem Handbuch:
        http://dev.mysql.com/doc/refman/5.5/en/char.html

        VARCHAR ist immer nur so lang, wie der String lang ist, maximal aber die angegebene Länge. CHAR belegt immer soviel Zeichen wie angegeben. Der Rest wird mit Leerzeichen aufgefüllt.

        Wird varchar nun auch abgeschnitten, oder nicht?

        Ja, wenn das Feld zu klein dimensioniert ist.

        dedlfix.

        1. Liebe Mitdenker,
          liebe Wissende,
          liebe Neugierige,

          ja!

          [...]

          Danke.

          Scheint heute ein MySQL-Abend zu werden. Wollte nur mal schnell die Server auf einen einheitlichen Stand bringen. Jetzt habe ich noch einen Debian Squeeze dazwischen, auf dem noch MySQL 5.1.72 läuft. Das lässt sich aus dem Standard-Repository auch nicht einfach so upgraden. Da ist 5.1.73-1 der neueste, der angeboten wird. Erst ab Wheezy ist 5.5.40-0+wheezy1 verfügbar.

          Wenn ich ChrisB richtig verstanden habe, funktioniert eine saubere utf8-Unterstützung aber erst ab MySQL 5.5.3

          Ich trau mich da nicht unbedingt ran, das per Remote (SSH-Konsole) aufzubohren. Wheezy bringt auch die neue Kernel-Generation mit. Da hatte ich schon bei mehreren Servern leichte Startprobleme.

          Was passiert da mit den utf8-coderiten Tabellen dann nicht?
          Kann ich die trotzdem erstmal weiterbenutzen lassen, bis ich den Hoster ums Upgrade bitten kann?

          Bisher sind keine Klagen gekommen. Kann ja sein, dass einfach kein Zeichen mit mehr als drei Bytes Länge dabei war, oder gibt es noch andere Einschränkungen, die den Betrieb gefährden könnten?

          Spirituelle Grüße
          Euer Robert

          --
          Möge der Forumsgeist wiederbelebt werden!
          1. Tach!

            Wenn ich ChrisB richtig verstanden habe, funktioniert eine saubere utf8-Unterstützung aber erst ab MySQL 5.5.3

            Jein. Wenn du selten verwendete Zeichen verwenden möchtest, dann brauchst du das, aber für den Hausgebrauch bin ich mit nur der BMP-Unterstützung auch noch nicht an Grenzen gestoßen.

            Was passiert da mit den utf8-coderiten Tabellen dann nicht?
            Kann ich die trotzdem erstmal weiterbenutzen lassen, bis ich den Hoster ums Upgrade bitten kann?

            Meines Wissens ist das nur der Unterschied zwischen nur BPM oder alles.

            Bisher sind keine Klagen gekommen. Kann ja sein, dass einfach kein Zeichen mit mehr als drei Bytes Länge dabei war, oder gibt es noch andere Einschränkungen, die den Betrieb gefährden könnten?

            Frag mal Gunnar, der kennt garantiert ein paar "wichtige" Zeichen außerhalb der BMP. ;)

            dedlfix.

            1. Liebe Mitdenker,
              liebe Wissende,
              liebe Neugierige,

              ja!

              Frag mal Gunnar, der kennt garantiert ein paar "wichtige" Zeichen außerhalb der BMP. ;)

              *ROTFL*

              Ich habe noch ein paar wilde Tests abgesetzt und es ist nichts ungewöhnliches passiert...
              Ich lass das also erstmal so, bis der Hoster auf Wheezy aufstocken mag.

              Spirituelle Grüße
              Euer Robert

              --
              Möge der Forumsgeist wiederbelebt werden!
      2. Liebe Mitdenker,

        Charset, Collation muss stimmen und das Programm muss mit MySQL per UTF-8 kommunizieren (SET NAMES ...), dann passt alles rein.

        Was hat die Collation mit dem Speicherplatzbedarf des Feldes zu tun?

        Gar nichts hast rechts. Aber wenn Du richtig mit kodierten Strings arbeiten willst, sollte die schon passen.

        Was ist an 'set names' besser, als an der PHP-Funktion mysqli_set_charset()?

        Das musst Du selbst rausfinden. In Perl ists so, dass mysql_enable_utf8 => 1 die Kommunikation bidirektional auf utf-8 schaltet, d.h., dass die Abfragen utf-8-kodierte Zeichenketten liefern und dem Statement übergebene Oktetten automatisch zu UTF-8-Strings werden. Mit "set names utf8" allein muss sich der Programmierer selbst um die Kodierung kümmern, er muss für die Inserts aus den Oktetten UTF-8-kodierte Strings machen und das auch aus den Oktetten, welche zurückkommen.

        Dein Versuch hinkt allerdings. Du müsstest mal 9 (oder 10?) Zeichen einfügen, die jedes vier Oktetts benötigen. ...

        Es funktioniert auch mit text char(10), auch da kann ich 10 €-Zeichen einfügen, das sind 30 Bytes. Ob MySQL je nach Version 3,4 oder gar 5 Bytes für den Charset utf8 reserviert, sollte im Handbuch stehen. Auf jeden Fall wird mit CHARSET=UTF8 mehr Platz reserviert, der jedoch nur dann genutzt werden kann, wenn Charset auch der Kommunikation (Sitzung) bekannt ist, ansonsten gilt die Byte-Semantics: char(10) => 10 Bytes passen da rein.

        Set Names UTF8
        Character-Semantics: char(10) => 10 Zeichen passen rein

        Btw., die neueste JS-Library stringview.js erlaubt 5 Bytes für UTF-8.

        MfG

    2. Liebe Mitdenker,
      liebe Wissende,
      liebe Neugierige,

      ja!

      Das mit der Länge hat sich durch ChrisBs Posting erledigt.

      Bleibt nur noch die Frage, was besser ist:

      'set names' oder mysqli_set_charset()?

      Spirituelle Grüße
      Euer Robert

      --
      Möge der Forumsgeist wiederbelebt werden!
  3. Hi,

    Wie passt das zusammen.
    UTF-8 benötigt doch eigentlich vier Bytes pro Zeichen:
    http://de.wikipedia.org/wiki/UTF-8

    *Bis zu* vier. Für viele Zeichen sind es aber weniger.

    Spielt MySQL hier Statistik-Roulette?

    Nein. Lange Zeit hat MySQL UTF-8 gar nicht voll unterstützt, sondern nur Zeichen bis zu drei Byte Länge erlaubt.

    Seit 5.5.3 gibt es das Encoding utf8mb4 – und das bietet dann endlich vollen UTF-8-Support
    https://mathiasbynens.be/notes/mysql-utf8mb4

    MfG ChrisB

    --
    Autocomplete has spoiled me to a point where it happens every so often that I encounter a CAPTCHA, and I just type in the first character … and then wait for the rest of the code to be automatically suggested :/
    1. Liebe Mitdenker,
      liebe Wissende,
      liebe Neugierige,

      ja!

      Wie passt das zusammen.
      UTF-8 benötigt doch eigentlich vier Bytes pro Zeichen:
      http://de.wikipedia.org/wiki/UTF-8

      *Bis zu* vier. Für viele Zeichen sind es aber weniger.

      Spielt MySQL hier Statistik-Roulette?

      Nein. Lange Zeit hat MySQL UTF-8 gar nicht voll unterstützt, sondern nur Zeichen bis zu drei Byte Länge erlaubt.

      Seit 5.5.3 gibt es das Encoding utf8mb4 – und das bietet dann endlich vollen UTF-8-Support
      https://mathiasbynens.be/notes/mysql-utf8mb4

      Danke. Das war äußerst erhellend!

      Es werden ja tatsächlich nur 21 Bits von 32 für die eigentlichen Daten benutzt bei UTF8. Jetzt verstehe ich auch den enormen Anstieg des Speicherplatzbedarfes, nachdem wir unsere Datenbanken von ISO auf UTF8 umgestellt haben. Da werden tatsächlich drei Bytes verballert, auch wenn nur eins benötigt werden würde.

      Spirituelle Grüße
      Euer Robert

      --
      Möge der Forumsgeist wiederbelebt werden!