Groß- und Kleinschreibung für Fortgeschrittene: MySQL und lower_case_table_names

titelbild-lower-case

Die Groß- und Kleinschreibung stellt in der deutschen Sprache einige vor große Herausforderungen. Manchmal passiert exakt dieses Phänomen auch bei MySQL-Datenbanken.

Denn nicht jeder MySQL-Server geht mit allen „Rechtschreibregeln" gleich um. In diesem Beitrag geht um die Grundregeln der Groß- und Kleinschreibung und Probleme, die daraus entstehen können.

Die Regeln oder was weißt 'duden'...

Wir versuchen an dieser Stelle, die Regeln etwas vereinfacht darzustellen. Dies hat aber keine Auswirkungen auf den Sachverhalt und die daraus möglicherweise entstehenden Probleme.

Datenbanken und Objekte (z.B. Tabellen !) korrespondieren bei MySQL mit Ordnern und Dateien im Filesystem.

Wird beispielsweise die Datenbank „Rechtschreibung" mit der Tabelle „Regeln" erzeugt, so befinden sich dafür unterhalb des Datenbankverzeichnisses (datadir) des Systems entsprechende Einträge.

mysql> create database Rechtschreibung;
Query OK, 1 row affected (0.02 sec)
mysql> create table Rechtschreibung.Regeln ( wordno int primary key auto_increment, word varchar(20));
Query OK, 0 rows affected (0.07 sec)


bash-4.2# cd /var/lib/mysql/Rechtschreibung/
bash-4.2# ls -la
total 88
drwxr-x---  2 mysql mysql   4096 Aug 26 13:17 .
drwxr-x--x 12 mysql mysql   4096 Aug 26 13:17 ..
-rw-r-----  1 mysql mysql 114688 Aug 26 13:17 Regeln.ibd 

Schreib wie du sprichst?!

Die Ordner und Dateien werden dabei in unserem Fall exakt in der Schreibweise (Groß- und Kleinschreibung) erstellt, wie sie im SQL (DDL) definiert wurden.

Genau an dieser Stelle treten die ersten Probleme auf. Dateisysteme, die case-sensitive arbeiten (eher bei Linux zu finden) lassen einen Datenbank- und/oder Objektnamen mehrfach zu, solange die Schreibweise sich unterscheidet:

# Linux Server
mysql> create database rechtschreibung;
Query OK, 1 row affected (0.01 sec)
mysql> create database RECHTSCHREIBUNG;
Query OK, 1 row affected (0.01 sec) 

Auf Windows-Systemen funktioniert dies nicht, da dort die Dateisysteme in aller Regel case-insensitive sind. Der Name einer Datenbank oder eines Objekts kann nur einmal definiert werden und zwar unabhängig von der entsprechenden Groß- und Kleinschreibung.

Aber nicht nur beim Anlegen von Objekten ist die Schreibweise entscheidend (zumindest bei case-sensitiven Systemen):

mysql> insert into Regeln values (null, 'Rechtschreibreform');
Query OK, 1 row affected (0.01 sec)
mysql> insert into regeln values (null, 'Rechtschreibfehler');
ERROR 1146 (42S02): Table 'Rechtschreibung.regeln' doesn't exist 

Wird ein Objektname nicht korrekt spezifiziert, so kommt es zu einem Fehler (object does not exist). Auf einem Windows-System hätten beide INSERTs funktioniert (case-insensitive).

Es gibt da ein Missverständnis…

Das oben beschriebene Problem ist bereits unschön genug. Die Probleme können aber noch schlimmer werden und zu schweren Missverständnissen oder Kommunikationsproblemen führen. Bei einem unserer Kunden sollte ein System von Windows nach Linux repliziert werden. Zusätzlich bestand der Applikationshersteller über seine Installationsvorgaben daruf, dass der Parameter „lower_case_table_names" auf 0 zu setzen sei. Per Default steht diese Einstellung auf Windows-Systemen seit langer Zeit auf 1.

Das erste Problem bestand darin, dass das Backup-Werkzeug mysqldump, sofern es gegen eine Windows MySQL-DB arbeitet, alle Objektnamen in Kleinschreibweise konvertiert. Die Tabellen, die unter Windows (dank der Konfiguration von lower_case_table_names = 0) Großbuchstaben hatten, wurden auf dem Linux Server in Kleinschreibweise erzeugt. Der erste Applikationstest schlug fehl, da weder die Datenbank noch die Tabellen zu finden waren. Dieses Problem konnte jedoch über entsprechende RENAME-Kommandos schnell gefixt wurden.

Bei der im Anschluss konfigurierten Replikation kann es ebenfalls zu Problemen kommen, da die Entwickler sich eben nicht konsequent an die korrekte Schreibweise gehalten haben. Alle paar hundert Transaktionen wurde mal ein Tabellenname klein geschrieben und in dieser Schreibweise in das Replikations-log (bin-log) übernommen. Während das Windows-System diesen Fehler ignorierte (case-insensitive) und die Transaktion zuließ und protokollierte, blieb der Slave stehen, da er diesen Objektnamen (zumindest in Kleinschreibweise) nicht kannte.

Rechtschreibkorrektur

Dieses Verhalten ist natürlich unschön. Wir haben oftmals erlebt, dass Applikationen, die unter einem Windows-System entwickelt und getestet wurden, bei der Inbetriebnahme unter Linux auf Fehler gelaufen sind, da sich die Entwickler nicht an Namenskonventionen („Wir schreiben alles klein!") gehalten haben.

Wir empfehlen von daher seit langer Zeit den bewussten Einsatz des Parameters „lower_case_table_names" unabhängig von zugrundeliegenden Betriebs- und Dateisystemen.

Er kann auf drei Arten konfiguriert werden:

  • 0: Objekte werden so erzeugt, wie sie geschrieben werden, unabhängig davon, ob das Dateisystem case-sensitive ist oder nicht.
  • 1: Objekte werden bei Erzeugen und Nachschlagen (lookup) in Kleinschreibweise konvertiert (mittlerweile der default bei Windows)
  • 2: Objekte werden gemäß der Definition erzeugt (also case-sensitive). Beim lookup wird aber immer in Kleinschreibweise konvertiert


Eine detaillierte Beschreibung zu diesem Parameter finden Sie hier:

https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_lower_case_table_names

https://dev.mysql.com/doc/refman/8.0/en/identifier-case-sensitivity.html

Setzen Sie, wenn Sie können, „lower_case_table_names" auf 1. Egal auf welchem Betriebssystem und/oder Dateisystem Sie arbeiten. Die Objekte werden immer in Kleinschreibweise erzeugt und gesucht. Sollte der Entwickler im Code Großbuchstaben oder sonstige, abweichende Schreibweisen verwenden, werden die Objekte beim Lookup (oder Erzeugen) in Kleinbuchstaben konvertiert und konsequent gefunden. Zusätzlich sorgt diese Einstellung dafür, dass Objektnamen nur einmalig verwendet werden können.

Fazit: Beachten Sie die goldene Regel

Der Parameter „lower_case_table_names" dürfte für die erfahrenden MySQL DBAs ein alter Hut sein. An der goldenen Regel hat sich aus unserer Perspektive nichts geändert. Setzen Sie den Parameter auf 1 (bzw. belassen Sie ihn bei Windows dort), solange Sie nicht einen triftigen Grund für eine abweichende Konfiguration haben. Das Verhalten von „mysqldump" gegenüber Windows-Systemen (Konvertierung in Kleinbuchstaben) hatten wir so nicht erwartet. Tatsächlich wurden diesbezüglich auch Bugs bei MySQL gemeldet, die mit dem Verweis auf die oben stehende Dokumentation und der Default-Konfiguration von Windows geschlossen wurden.

By accepting you will be accessing a service provided by a third-party external to https://blog.ordix.de/