Anhang A. Probleme und häufig auftretende Fehler
Zurück |  | Weiter

## Anhang A. Probleme und häufig auftretende Fehler

In diesem Anhang sind einige häufige Probleme und Fehlermeldungen aufgeführt, auf die Sie vielleicht stoßen werden. Außerdem wird beschrieben, wie man die Fehlerursachen findet und die Probleme behebt.

## A.1. Wie man feststellt, was Probleme verursacht

Wenn Sie auf ein Problem stoßen, müssen Sie als Erstes herausfinden, von welchem Programm oder Hardwareteil es verursacht wird.

- Die folgenden Symptome sprechen für Probleme mit der Hardware (Arbeitsspeicher, Motherboard, CPU oder Festplatte) oder mit dem Kernel:

  - Die Tastatur funktioniert nicht. Dies lässt sich normalerweise durch Drücken der Feststelltaste herausfinden. Wenn sich das Feststell-Licht dabei nicht ändert, müssen Sie Ihre Tastatur austauschen. (Bevor Sie das tun, sollten Sie allerdings den Computer neu starten und alle Kabelverbindungen der Tastatur überprüfen.)

  - Der Mauszeiger bewegt sich nicht.

  - Der Computer antwortet nicht auf die Ping-Versuche eines Remote-Computers.

  - Andere Programme, die nichts mit MySQL zu tun haben, funktionieren ebenfalls nicht.

  - Ihr System führt überraschend einen Neustart durch. (Ein fehlerhaftes Benutzerprogramm darf nie in der Lage sein, Ihr System herunterzufahren.)

  In diesem Fall überprüfen Sie als Erstes alle Ihre Kabel und lassen ein Diagnosetool laufen, um Ihre Hardware zu überprüfen. Außerdem schauen Sie nach, ob es irgendwelche Patches, Updates oder Service Packs für Ihr Betriebssystem gibt, die Ihr Problem lösen könnten. Auch die Aktualität Ihrer Bibliotheken (zum Beispiel `glibc`) muss überprüft werden.

  Es ist immer gut, einen Computer mit ECC-Memory zu überprüfen, um eventuelle Arbeitsspeicherprobleme frühzeitig zu finden.

- Wenn Ihre Tastatur gesperrt ist, können Sie dies vielleicht beheben, indem Sie sich von einem anderen Computer aus auf Ihrem Rechner anmelden und `kbd_mode -a` ausführen.

- Bitte fahnden Sie in Ihrem Systemlog (`/var/log/messages` oder ähnlich) nach Ursachen für Ihr Problem. Wenn Sie denken, dass es an MySQL liegt, sollten Sie auch die Logdateien von MySQL untersuchen. Siehe Abschnitt 5.12, „Die MySQL-Logdateien“.

- Wenn Sie nicht der Ansicht sind, dass es sich um ein Hardwareproblem handelt, müssen Sie herausfinden, welches Programm die Probleme macht. Mit top, ps, Task-Manager oder einem ähnlichen Tool können Sie nachschauen, welches Programm die gesamte CPU mit Beschlag belegt oder den Computer sperrt.

- Mit top, df oder einem ähnlichen Programm können Sie prüfen, ob Arbeitsspeicher, Festplattenplatz, Dateideskriptoren oder eine andere wichtige Ressource ausgeht.

- Ist das Problem ein außer Kontrolle geratener Prozess, können Sie versuchen, diesen anzuhalten. Wenn er sich weigert, liegt wahrscheinlich ein Fehler im Betriebssystem vor.

Wenn Sie nach gründlicher Prüfung aller anderen Möglichkeiten zu dem Schluss kommen, dass der MySQL Server oder ein MySQL-Client das Problem verursacht hat, ist es an der Zeit, einen Bugreport für unsere Mailingliste oder unser Support-Team zu verfassen. Bitte beschreiben Sie darin sehr genau, wie sich das System verhält und was Ihrer Meinung nach vorgeht. Außerdem schreiben Sie bitte Ihre Einschätzung, was die Wurzel des Problems sein könnte. Bitte berücksichtigen Sie alle im vorliegenden Kapitel beschriebenen Situationen und sagen Sie genau, wie die Probleme auftreten, wenn Sie Ihr System überprüfen. Ausgabe und Fehlermeldungen von Programmen und Logdateien können Sie mit „Kopieren und Einfügen“ in Ihren Fehlerbericht übernehmen.

Versuchen Sie, detailliert zu beschreiben, welches Programm nicht funktioniert und welche Symptome vorhanden sind. Wir haben schon viele Bugreports gesehen, in denen es lediglich hieß: „Das System funktioniert nicht“. So bekommen wir keine Informationen, die uns helfen, das Problem zu beheben.

Wenn ein Programm abstürzt, sind folgende Informationen nützlich:

- Hat das Programm einen Segmentierungsfehler gemacht (hat es einen Core Dump erstellt)?

- Belegt das Programm sämtliche Prozessorzeit? Dies können Sie mit top überprüfen. Lassen Sie das Programm für eine Weile laufen, vielleicht führt es ja nur gerade eine rechenintensive Operation durch.

- Wenn der mysqld-Server Probleme macht: Können Sie mit mysqladmin -u root ping oder mysqladmin -u root processlist irgendeine Antwort von ihm bekommen?

- Was sagt Ihr Clientprogramm, wenn Sie versuchen, sich mit dem MySQL Server zu verbinden? (Versuchen Sie es zum Beispiel mit mysql.) Blockiert der Client? Gibt das Programm irgendetwas aus?

Wenn Sie uns einen Bugreport schicken, halten Sie sich bitte an die in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“, beschriebene Vorgehensweise.

## A.2. Einige häufige Fehler bei der Benutzung von MySQL

In diesem Abschnitt werden einige Fehler beschrieben, auf die Benutzer häufig bei der Ausführung von MySQL-Programmen stoßen. Die Probleme zeigen sich zwar bei der Ausführung von Clientprogrammen, aber die Lösung ist in vielen Fällen eine Konfigurationsänderung des MySQL Servers.

### A.2.1. `Access denied`-Fehler

Ein `Access denied`-Fehler kann viele Ursachen haben. Oft hängt er damit zusammen, welchen MySQL-Konten der Server die Benutzung von Clientprogrammen gestattet. Siehe Abschnitt 5.8.8, „Gründe für `Access denied`-Fehler“, und Abschnitt 5.8.2, „Wie das Berechtigungssystem funktioniert“.

### A.2.2. `Can't connect to [local] MySQL server`-Fehler

Auf Unix hat ein MySQL-Client zwei Möglichkeiten, sich mit dem mysqld-Server zu verbinden: Entweder verwendet er eine Unix-Socketdatei (nach Voreinstellung `/tmp/mysql.sock`), um sich über eine Datei im Dateisystem zu verbinden, oder er verwendet TCP/IP, um sich über eine Portnummer zu verbinden. Eine Verbindung über eine Unix-Socketdatei ist schneller als TCP/IP, kann aber nur genutzt werden, wenn sich der Client mit einem Server auf demselben Computer verbindet. Der Weg über die Unix-Socketdatei wird gewählt, wenn Sie keinen Hostnamen oder `localhost` angeben.

Wenn der MySQL Server auf Windows 9x oder Me läuft, können Sie sich nur per TCP/IP verbinden. Wenn er auf Windows NT, 2000, XP oder 2003 läuft und mit der Option `--enable-named-pipe` gestartet wird, können Sie sich auch mit Named Pipes verbinden, wenn der Client auf demselben Host wie der Server läuft. Der Name der Named Pipe ist nach Voreinstellung `MySQL`. Wenn Sie für die Verbindung mit mysqld keinen Hostnamen angeben, versucht ein MySQL-Client als Erstes eine Verbindung mit der Named Pipe. Wenn das nicht klappt, verbindet er sich mit dem TCP/IP-Port. Indem Sie `.` als Hostnamen angeben, zwingen Sie Windows zur Verwendung von Named Pipes.

Der Fehler (2002) `Can't connect to ...` bedeutet normalerweise, dass auf dem System kein MySQL Server läuft oder dass Sie bei Ihrem Verbindungsversuch einen verkehrten Unix-Socketdateinamen oder TCP/IP-Port angegeben haben.

Prüfen Sie als Erstes, ob auf Ihrem Serverhost ein Prozess namens mysqld läuft. (Hierzu verwenden Sie auf Unix ps xa | grep mysqld und auf Windows den Task- Manager.) Wenn kein solcher Prozess läuft, starten Sie den Server. Siehe hierzu Abschnitt 2.9.2.3, „Probleme mit dem Start des MySQL Servers“.

Läuft ein mysqld-Server, so überprüfen Sie ihn mit den folgenden Befehlen. Die Portnummer oder der Name der Unix-Socketdatei können in Ihrem Fall abweichen. `host_ip` ist die IP-Nummer des Computers, auf welchem der Server ausgeführt wird.

    shell> mysqladmin version
    shell> mysqladmin variables
    shell> mysqladmin -h `hostname` version variables
    shell> mysqladmin -h `hostname` --port=3306 version
    shell> mysqladmin -h host_ip version
    shell> mysqladmin --protocol=socket --socket=/tmp/mysql.sock version

Beachten Sie, dass Backticks anstelle von Anführungszeichen für den `hostname`-Befehl verwendet werden. Diese sorgen dafür, dass die Ausgabe von `hostname` (also des aktuellen Hostnamens) in den Befehl mysqladmin eingesetzt wird. Wenn Sie keinen `hostname`-Befehl zur Verfügung haben oder mit Windows arbeiten, können Sie den Hostnamen Ihres Computers hinter der Option `-h` manuell eingeben (ohne Backticks). Oder Sie versuchen, sich mit `-h 127.0.0.1` über TCP/IP mit dem lokalen Host zu verbinden.

Der Fehler `Can't connect to local MySQL server` könnte aus folgenden Gründen auftreten:

- mysqld läuft nicht. Vergewissern Sie sich, ob der Prozess mysqld in der Prozessliste Ihres Betriebssystems auftaucht.

- Sie führen einen MySQL Server auf Windows mit vielen TCP/IP-Verbindungen aus. Wenn es häufiger vorkommt, dass Ihre Clients diesen Fehler melden, finden Sie an folgender Stelle einen Workaround: Abschnitt A.2.2.1, „`Connection to MySQL server failing on Windows`-Fehler“.

- Ihr System verwendet MIT-pthreads. Wenn Sie auf einem System arbeiten, das keine nativen Threads kennt, verwendet mysqld das Package MIT-pthreads (siehe Abschnitt 2.1.1, „Betriebssysteme, die von MySQL unterstützt werden“). Allerdings unterstützen nicht alle MIT-pthreads Unix-Socketdateien. Auf einem System ohne Socketdateiunterstützung müssen Sie bei einer Serververbindung den Hostnamen immer explizit angeben. Versuchen Sie, mit folgendem Befehl die Serververbindung zu überprüfen:

      shell> mysqladmin -h `hostname` version

- Jemand hat die von mysqld verwendete Unix-Socketdatei entfernt (standardmäßig `/tmp/mysql.sock`). Vielleicht haben Sie ja einen cron-Job, der alte Dateien aus dem Verzeichnis `/tmp` löscht. Mit mysqladmin version können Sie sich vergewissern, dass die Unix-Socketdatei, die mysqladmin benötigt, auch tatsächlich existiert. Wenn dies das Problem ist, müssen Sie den cron-Job so abändern, dass er `mysql.sock` nicht mehr entfernt, oder die Socketdatei an einen anderen Ort verlagern. Siehe Abschnitt A.4.5, „Wie Sie die MySQL-Socketdatei `/tmp/mysql.sock` schützen oder ändern“.

- Sie haben den mysqld-Server zwar mit der Option `--socket=/path/to/socket` gestartet, aber vergessen, den Clientprogrammen den neuen Namen der Socketdatei mitzuteilen. Wenn Sie den Socketpfadnamen für den Server ändern, müssen Sie auch die MySQL-Clients entsprechend benachrichtigen. Dies erledigen Sie, indem Sie dieselbe `--socket`-Option einsetzen, wenn Sie die Clientprogramme ausführen. Außerdem müssen Sie gewährleisten, dass die Clients ein Zugriffsrecht auf die `mysql.sock`-Datei haben. Um herauszufinden, wo die Socketdatei liegt, tun Sie Folgendes:

      shell> netstat -ln | grep mysql

  Siehe Abschnitt A.4.5, „Wie Sie die MySQL-Socketdatei `/tmp/mysql.sock` schützen oder ändern“.

- Sie arbeiten auf Linux und ein Server-Thread ist ausgefallen (mit Core Dump). In diesem Fall müssen Sie auch die anderen mysqld-Threads anhalten (zum Beispiel mit `kill` oder mit dem `mysql_zap`-Skript), bevor Sie den MySQL Server neu starten können. Siehe Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.

- Der Server oder das Clientprogramm hat nicht die richtigen Zugriffsberechtigungen für das Verzeichnis mit der Unix-Socketdatei oder der Socketdatei selbst. In diesem Fall müssen Sie die Berechtigungen so ändern, dass der Server und die Clients an diese Dateien herankommen, oder mysqld mit einer `--socket`-Option neu starten, die eine Socketdatei in einem Verzeichnis angibt, wo der Server sie anlegen kann und die Clients auf sie zugreifen können.

Wenn Sie die Fehlermeldung `Can't connect to MySQL server on some_host` bekommen, können Sie mit folgenden Mitteln herausfinden, wo das Problem liegt:

- Prüfen Sie, ob der Server auf diesem Host läuft, indem Sie `telnet some_host 3306` ausführen und dann die Eingabetaste einige Male drücken. (3306 ist die Standardnummer für den MySQL-Port. Ändern Sie den Wert, wenn Ihr Server einen anderen Port verwendet.) Wenn ein MySQL Server auf diesem Port läuft und lauscht, müssten Sie eine Antwort bekommen, die auch die Versionsnummer des Servers angibt. Erhalten Sie stattdessen einen Fehler wie beispielsweise `telnet: Unable to connect to remote host: Connection refused`, dann ist auf dem angegebenen Port kein Server zu erreichen.

- Wenn der Server auf dem lokalen Host läuft, können Sie versuchen, sich per mysqladmin -h localhost variables über die Unix-Socketdatei zu verbinden. Überprüfen Sie, auf welcher TCP/IP-Portnummer der Server lauscht (also den Wert der Variablen `port`).

- Vergewissern Sie sich, dass der mysqld-Server nicht mit der Option `--skip-networking` gestartet wurde. Ansonsten können Sie sich nicht per TCP/IP verbinden.

- Vergewissern Sie sich, dass keine Firewall den Zugriff auf MySQL verhindert. Anwendungen wie ZoneAlarm und die Windows XP-Firewall müssen unter Umständen speziell konfiguriert werden, damit sie den externen Zugriff auf einen MySQL Server erlauben.

#### A.2.2.1. `Connection to MySQL server failing on Windows`-Fehler

Wenn Sie einen MySQL Server auf Windows mit vielen TCP/IP-Verbindungen ausführen und Ihre Clients häufig einen `Can't connect to MySQL server`-Fehler melden, könnte es sein, dass Windows nicht genügend vorübergehende (kurzlebige) Ports erlaubt, um diese Verbindungen zu ermöglichen.

Nach Voreinstellung gestattet Windows 5000 vorübergehende (kurzlebige) TCP-Ports. Wenn ein Port geschlossen wird, verbleibt er 120 Sekunden lang in einem `TIME_WAIT`-Status. Wird die Verbindung in diesem Status wiederverwendet, so entstehen viel weniger Kosten als bei der Einrichtung einer neuen Verbindung. Allerdings steht der Port vor Ablauf dieser Zeit nicht zur Verfügung.

Wenn Sie nur einen kleinen Vorrat verfügbarer TCP-Ports (5000) haben und viele dieser Ports in kurzer Zeit geöffnet und mit dem `TIME_WAIT`-Status wieder geschlossen werden, kann es leicht passieren, dass Ihnen die Ports ausgehen. Es gibt zwei Möglichkeiten, dieses Problem in den Griff zu bekommen:

- Sie sorgen dafür, dass die TCP-Ports nicht so schnell aufgebraucht werden, indem Sie, wo immer es möglich ist, Verbindungspooling oder persistente Verbindungen in Betracht ziehen.

- Sie ändern einige Einstellungen in der Windows-Registrierung (siehe weiter unten).

Wichtig: Im folgenden Verfahren wird die Windows-Registrierung geändert. Bevor Sie dies tun, müssen Sie Ihre Registrierung unbedingt sichern und genau wissen, wie Sie sie wiederherstellen können, falls etwas geschieht. Wie man die Registrierung sichert, wiederherstellt und bearbeitet, verrät Ihnen folgender Artikel aus der Microsoft Knowledge Base: http://support.microsoft.com/kb/256986/EN-US/.

1. Starten Sie den Registrierungs-Editor (`Regedt32.exe`).

2. Suchen Sie folgenden Registrierungsschlüssel:

       HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

3. Klicken Sie im Menü `Bearbeiten` auf `Wert hinzufügen` und fügen Sie dann folgenden Registrierungswert ein:

       Value Name: MaxUserPort
       Data Type: REG_DWORD
       Value: 65534

   Dieser Wert stellt ein, wie viele vorübergehende Ports einem Benutzer zur Verfügung stehen. Der zulässige Wertebereich liegt zwischen 5000 und 65534 (Dezimalsystem). Der Standardwert ist 0x1388 (5000 dezimal).

4. Klicken Sie im Menü `Bearbeiten` auf `Wert hinzufügen` und fügen Sie dann folgenden Registrierungswert hinzu:

       Value Name: TcpTimedWaitDelay
       Data Type: REG_DWORD
       Value: 30

   Hiermit stellen Sie ein, wie viele Sekunden eine Verbindung mit einem TCP-Port im `TIME_WAIT`-Status verbleibt, ehe sie geschlossen wird. Der zulässige Wertebereich liegt zwischen 0 (null) und 300 (dezimal). Der Standardwert ist 0x78 (120 dezimal).

5. Schließen Sie den Registrierungs-Editor.

6. Starten Sie den Computer neu.

Hinweis: Um die obigen Änderungen rückgängig zu machen, löschen Sie einfach die Registrierungseinträge, die Sie erstellt haben.

### A.2.3. `Client does not support authentication protocol`

MySQL 5.1 verwendet ein Authentifizierungsprotokoll, das auf einem Passwort-Hash-Algorithmus basiert, der mit älteren Clients (vor Version 4.1) inkompatibel ist. Wenn Sie den Server von 4.1 auf die neue Version aufrüsten, können Verbindungsversuche mit einem älteren Client folgenden Fehler verursachen:

    shell> mysql
    Client does not support authentication protocol requested
    by Server; consider upgrading MySQL client

Für dieses Problem gibt es folgende Lösungsansätze:

- Sie aktualisieren alle Clientprogramme, sodass sie die Clientbibliothek von 4.1.1 oder eine neuere Version benutzen.

- Wenn Sie mit einem Clientprogramm einer Version vor 4.1 auf den Server zugreifen, verwenden Sie ein Konto, das noch ein Passwort aus der Zeit von vor 4.1 hat.

- Stellen Sie das Passwort für Benutzer, die ein älteres Clientprogramm als 4.1 verwenden, im Stil der Version von vor 4.1 ein. Dies können Sie mit der `SET PASSWORD`-Anweisung oder der `OLD_PASSWORD()`-Funktion tun:

      mysql> SET PASSWORD FOR
          -> 'some_user'@'some_host' = OLD_PASSWORD('newpwd');

  Alternativ können Sie auch `UPDATE` und `FLUSH PRIVILEGES` einsetzen:

      mysql> UPDATE mysql.user SET Password = OLD_PASSWORD('newpwd')
          -> WHERE Host = 'some_host' AND User = 'some_user';
      mysql> FLUSH PRIVILEGES;

  In diesen Beispielen müssen Sie „`newpwd`“ durch das neue, von Ihnen gewählte Passwort ersetzen. Da MySQL Ihnen das Originalpasswort nicht verraten kann, müssen Sie ein neues aussuchen.

- Veranlassen Sie den Server, den älteren Passwort-Hashing-Algorithmus zu verwenden:

  1. Starten Sie mysqld mit der Option `--old-passwords`.

  2. Weisen Sie jedem Konto, dessen Passwort auf das längere 4.1-Fomat umgestellt wurde, ein Passwort im alten Format zu. Welche Konten das sind, verrät Ihnen folgende Anfrage:

         mysql> SELECT Host, User, Password FROM mysql.user
             -> WHERE LENGTH(Password) > 16;

     Für jeden Konteneintrag, den der Server zeigt, nehmen Sie die Werte `Host` und `User` und weisen mit der Funktion `OLD_PASSWORD()` und `SET PASSWORD` oder `UPDATE` ein neues Passwort zu, wie oben beschrieben.

Hinweis: In älteren PHP-Versionen unterstützt die `mysql`-Erweiterung nicht das Authentifizierungsprotokoll von MySQL 4.1.1 und höher. Das gilt unabhängig von der verwendeten PHP-Version. Wenn Sie die `mysql`-Erweiterung mit MySQL 4.1 oder höher nutzen möchten, müssen Sie unter Umständen einen der oben beschriebenen Wege einschlagen, um MySQL für ältere Clients zu konfigurieren. Die `mysqli`-Erweiterung (die in PHP 5 für "MySQL, Improved" steht) ist kompatibel mit dem verbesserten Passwort-Hashing von MySQL 4.1 und höher. Hier ist keine spezielle Konfiguration für MySQL erforderlich, um diese MySQL-Clientbibliothek nutzen zu können. Weitere Informationen über die `mysqli`-Erweiterung finden Sie unter http://php.net/mysqli.

Unter Umständen kann auch die ältere `mysql`-Erweiterung mit der neuen MySQL-Clientbibliothek kompiliert werden. Dieser Vorgang ist jedoch nicht Thema unseres Referenzhandbuchs. Weitere Informationen finden Sie in der PHP-Dokumentation. Eventuell können Sie in solchen Fragen auch im MySQL with PHP forum Hilfe finden.

Hintergrundinformationen über Passwort-Hashing und Authentifizierung gibt es unter Abschnitt 5.8.9, „Kennwort-Hashing ab MySQL 4.1“.

### A.2.4. Interaktive Kennworteingabe schlägt fehl

MySQL-Clientprogramme fordern zur Eingabe eines Passworts auf, wenn sie mit der Option `--password` oder `-p` ohne einen Passwortwert dahinter aufgerufen werden:

    shell> mysql -u user_name -p
    Enter password:

Auf manchen Systemen kann es vorkommen, dass das Passwort funktioniert, wenn man es in einer Optionsdatei oder auf der Kommandozeile angibt, aber nicht, wenn man es interaktiv am `Enter password:`-Prompt eintippt. Dies geschieht, wenn die Bibliothek, die das System zum Lesen von Passwörtern zur Verfügung stellt, die Passwortwerte auf eine geringe Zeichenzahl einschränkt (in der Regel 8 Zeichen). Dieses Problem betrifft nicht MySQL, sondern die Systembibliothek. Um es zu lösen, müssen Sie entweder Ihr MySQL-Passwort auf einen Wert kürzen, der nur 8 Zeichen lang ist, oder es in eine Optionsdatei setzen.

### A.2.5. `Host '...' is blocked`-Fehler

Wenn folgender Fehler gemeldet wird, bedeutet dies, dass mysqld vom Host `'`host_name`'` viele Verbindungsanforderungen empfangen hat, die in der Mitte unterbrochen wurden:

    Host 'host_name' is blocked because of many connection errors.
    Unblock with 'mysqladmin flush-hosts'

Wie viele unterbrochene Anforderungen maximal zulässig sind, ist in der Systemvariablen `max_connect_errors` festgelegt. Nach `max_connect_errors` gescheiterten Anforderungen nimmt mysqld an, dass etwas nicht in Ordnung ist (beispielsweise ein Einbruchsversuch), und blockiert weitere Verbindungen dieses Hosts, bis Sie einen mysqladmin flush-hosts-Befehl oder eine `FLUSH HOSTS`-Anweisung geben. Siehe Abschnitt 5.2.2, „Server-Systemvariablen“.

Nach Voreinstellung blockiert mysqld einen Host nach 10 Verbindungsfehlern. Diesen Wert können Sie ändern, indem Sie den Server folgendermaßen starten:

    shell> mysqld_safe --max_connect_errors=10000 &

Wenn Sie diese Fehlermeldung für einen Host bekommen, prüfen Sie als Erstes, ob mit den TCP/IP-Verbindungen von diesem Host alles in Ordnung ist. Bei Netzwerkproblemen nützt es nichts, den Wert der Variablen `max_connect_errors` heraufzusetzen.

### A.2.6. `Too many connections`-Fehler

Wenn Sie beim Versuch einer Verbindung mit dem mysqld-Server einen `Too many connections`-Fehler bekommen, so bedeutet dies, dass alle verfügbaren Verbindungen von anderen Clients belegt sind.

Die Systemvariable `max_connections` legt fest, wie viele Verbindungen zulässig sind. Ihr Standardwert ist 100. Wenn Sie mehr Verbindungen benötigen, müssen Sie mysqld mit einem größeren Wert für diese Variable neu starten.

mysqld erlaubt in Wirklichkeit `max_connections+1` Clients eine Verbindung. Die eine zusätzliche Verbindung ist für Konten reserviert, die das `SUPER`-Recht haben. Indem Sie dieses Recht nur an Administratoren und nicht an normale Benutzer vergeben (diese benötigen es ohnehin nicht), kann sich ein Administrator selbst dann noch mit dem Server verbinden und mit der Anweisung `SHOW PROCESSLIST` eine Problemdiagnose vornehmen, wenn die Höchstzahl der unprivilegierten Clientverbindungen erreicht ist. Siehe Abschnitt 13.5.4.19, „`SHOW PROCESSLIST`“.

Wie viele Verbindungen MySQL maximal unterstützen kann, hängt von der Qualität der Thread-Bibliothek auf einer gegebenen Plattform ab. Linux oder Solaris müssten 500 bis 1.000 gleichzeitige Verbindungen dulden können, je nachdem, wie viel Arbeitsspeicher Sie haben und was Ihre Clients tun. Statische Linux-Binaries von MySQL AB können bis zu 4.000 Verbindungen unterstützen.

### A.2.7. `No free memory`-Fehler

Wenn Sie mit dem Clientprogramm mysql eine Anfrage absetzen und einen Fehler wie den folgenden ernten, so bedeutet dies, dass mysql zu wenig Arbeitsspeicher hat, um das vollständige Abfrageergebnis zu speichern:

    mysql: Out of memory at line 42, 'malloc.c'
    mysql: needed 8136 byte (8k), memory in use: 12481367 bytes (12189k)
    ERROR 2008: MySQL client ran out of memory

Dieses Problem beheben Sie, indem Sie zuerst prüfen, ob Ihre Anfrage korrekt ist. Ist es normal, dass sie so viele Zeilen zurückgibt? Wenn nicht, korrigieren Sie die Anfrage und versuchen es erneut. Andernfalls können Sie mysql mit der Option `--quick` aufrufen. Dann verwendet sie zum Abruf der Ergebnismenge die C-API-Funktion `mysql_use_result()`, die wesentlich weniger Last für den Client (aber mehr Last für den Server) bedeutet.

### A.2.8. `MySQL server has gone away`-Fehler

In diesem Abschnitt wird auch der hiermit verwandte `Lost connection to server during query`-Fehler behandelt.

Die häufigste Ursache eines `MySQL server has gone away`-Fehlers ist, dass der Server die Verbindung wegen eines Timeouts geschlossen hat. In diesem Fall wird normalerweise einer der folgenden Fehlercodes (je nach Betriebssystem) gemeldet:

Fehlercode | Beschreibung
`CR_SERVER_GONE_ERROR` | Der Client konnte keine Frage an den Server senden.
`CR_SERVER_LOST` | Der Client konnte zwar ohne Fehler auf den Server schreiben, erhielt aber keine (oder keine vollständige) Antwort auf die Frage.

Nach Voreinstellung schließt der Server die Verbindung, wenn nichts geschieht, nach acht Stunden. Dieses Zeitlimit können Sie in der Variablen `wait_timeout` ändern, wenn Sie mysqld starten. Siehe Abschnitt 5.2.2, „Server-Systemvariablen“.

Wenn Sie ein Skript verwenden, müssen Sie die Anfrage nur erneut absetzen, damit der Client sich automatisch erneut verbindet. Das setzt voraus, dass die automatische Neuverbindung im Client eingeschaltet ist (was beim `mysql`-Kommandozeilen-Client standardmäßig der Fall ist).

Oft kommen `MySQL server has gone away`-Fehler auch aus folgenden Gründen zustande:

- Sie (oder der Datenbankadministrator) haben den laufenden Thread mit einer `KILL`-Anweisung oder einem mysqladmin kill-Befehl angehalten.

- Sie haben versucht, eine Anfrage nach dem Schließen der Serververbindung abzusetzen. Dies weist auf einen Fehler in der Anwendungslogik hin, der korrigiert werden muss.

- Sie haben einen Timeout von der TCP/IP-Verbindung auf der Clientseite erhalten. Dazu kann es bei folgenden Befehlen kommen: `mysql_options(..., MYSQL_OPT_READ_TIMEOUT, ...)` oder `mysql_options(..., MYSQL_OPT_WRITE_TIMEOUT, ...)`. In diesem Fall können Sie Ihr Problem lösen, indem Sie den Timeout heraufsetzen.

- Sie haben einen Timeout auf der Serverseite und die automatische Neuverbindung ist im Client deaktiviert worden (das Flag `reconnect` in der `MYSQL`-Struktur ist gleich 0).

- Sie verwenden einen Windows-Client und der Server hat die Verbindung beendet (wahrscheinlich, weil `wait_timeout` abgelaufen ist), bevor der Befehl gegeben wurde.

  Das Problem mit Windows besteht darin, dass MySQL manchmal keinen Fehler vom Betriebssystem gemeldet bekommt, wenn es Daten in die TCP/IP-Verbindung mit dem Server schreibt. Stattdessen wird der Fehler erst bei dem Versuch gemeldet, Daten aus dieser Verbindung zu lesen.

  Selbst wenn das Flag `reconnect` in der `MYSQL`-Struktur gleich 1 ist, wird sich MySQL in diesem Fall nicht automatisch neu verbinden und die Anfrage neu absetzen, da es nicht wissen kann, ob der Server die ursprüngliche Anfrage bekommen hat oder nicht.

  Die Lösung ist entweder ein `mysql_ping` auf der Verbindung, falls seit der letzten Abfrage viel Zeit vergangen ist (so handelt auch `MyODBC`), oder eine Änderung von `wait_timeout` auf dem mysqld-Server auf einen Wert, der so hoch ist, dass es praktisch nie zu einem Timeout kommt.

- Solche Fehlermeldungen können Sie auch erhalten, wenn Sie an den Server eine zu große oder eine falsche Anfrage senden. Wenn mysqld ein Paket empfängt, das zu groß oder nicht ordnungsgemäß ist, nimmt das Programm an, dass mit dem Client etwas nicht stimmt, und schließt die Verbindung. Wenn Sie große Anfragen benötigen (zum Beispiel weil Sie mit umfangreichen `BLOB`-Spalten arbeiten), können Sie das Limit pro Anfrage heraufsetzen, indem Sie die Servervariable `max_allowed_packet` von ihrem Standardwert 1 Mbyte auf etwas Höheres heraufsetzen. Vielleicht müssen Sie auch die Paketgröße auf der Clientseite erhöhen. Über die Einstellung der Paketgröße können Sie unter Abschnitt A.2.9, „`Packet too large`-Fehler“, mehr erfahren.

- Ihre Verbindung wird auch abbrechen, wenn Sie ein Paket der Größe 16 Mbyte oder mehr verschicken und Ihr Client älter als Version 4.0.8 ist, während Ihr Server die Version 4.0.8 oder höher verwendet (oder umgekehrt).

- Eventuell kommt es auch zu dem Fehler `MySQL server has gone away`, wenn MySQL mit der Option `--skip-networking` gestartet wird.

- Während der Ausführung der Anfrage trat ein Fehler auf, der den Server angehalten hat.

Ob der MySQL Server abgestürzt und wieder hochgefahren ist, erfahren Sie, indem Sie mysqladmin version ausführen und auf die Uptime des Servers achten. Wenn die Clientverbindung unterbrochen war, weil mysqld abgestürzt und wieder hochgefahren ist, sollten Sie sich auf die Erforschung der Absturzursachen konzentrieren. Zuerst prüfen Sie, ob der Server bei derselben Anfrage erneut abstürzen wird. Siehe Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.

Mehr Informationen über unterbrochene Verbindungen bekommen Sie, wenn Sie mysqld mit der Option `--log-warnings=2` starten. Damit werden einige Verbindungsabbruchfehler in der Datei `hostname.err` protokolliert. Siehe Abschnitt 5.12.1, „Die Fehler-Logdatei“.

Wenn Sie einen Bugreport über dieses Problem schicken möchten, senden Sie uns bitte auch folgende Informationen:

- Angabe, ob der MySQL Server abgestürzt ist. Dies erfahren Sie aus dem Fehlerlog des Servers. Siehe Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.

- Wenn eine bestimmte Anfrage mysqld anhält und die beteiligten Tabellen mit `CHECK TABLE` vor Ausführung dieser Anfrage überprüft wurden: Können Sie dann einen reproduzierbaren Testfall herstellen? Siehe Abschnitt E.1.6, „Erzeugen eines Testfalls, wenn Sie Tabellenbeschädigung feststellen“.

- Welchen Wert hat die Systemvariable `wait_timeout` im MySQL Server? (Mit mysqladmin variables erhalten Sie den Wert dieser Variablen.)

- Haben Sie versucht, mysqld mit der Option `--log` auszuführen, um festzustellen, ob die Problemanfrage im Log auftaucht?

Siehe auch Abschnitt A.2.10, „Kommunikationsfehler/abgebrochene Verbindung“, und Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.

### A.2.9. `Packet too large`-Fehler

Ein Kommunikationspaket ist eine einzelne an den MySQL Server geschickte SQL-Anweisung oder eine einzelne an den Client geschickte Zeile.

Das größtmögliche Paket, das von einem oder an einen MySQL 5.1 Server oder -Client übermittelt werden kann, ist 1 Gbyte groß.

Wenn ein MySQL-Client oder der mysqld-Server ein Paket empfängt, dessen Größe `max_allowed_packet` Bytes übersteigt, löst er einen `Packet too large`-Fehler aus und schließt die Verbindung. Manche Clients melden auch einen `Lost connection to MySQL Server during query`-Fehler, wenn das Kommunikationspaket zu groß ist.

Da Client und Server jeweils ihre eigene `max_allowed_packet`-Variable haben, müssen Sie diese auf beiden Seiten erhöhen, wenn Sie größere Pakete verschicken möchten.

Der Standardwert der `max_allowed_packet`-Variable des Clientprogramms mysql ist 16 Mbyte. Um ihn zu erhöhen, starten Sie mysql wie folgt:

    mysql> mysql --max_allowed_packet=32M

So wächst die Paketgröße auf 32 MB.

Die maximale `max_allowed_packet`-Größe des Servers ist 1 MB. Sie können sie heraufsetzen, wenn der Server umfangreiche Anfragen verarbeiten muss (beispielsweise mit großen `BLOB`-Spalten). Um diese Variable auf 16 Mbytezu setzen, starten Sie den Server wie folgt:

    mysql> mysqld --max_allowed_packet=16M

Sie können `max_allowed_packet` auch mit einer Optiondatei einstellen. Um beispielsweise die Paketgröße für den Server auf 16 Mbytezu setzen, fügen Sie einer Optionsdatei folgende Zeilen hinzu:

    [mysqld]
    max_allowed_packet=16M

Der Wert dieser Variablen lässt sich ohne Sicherheitsrisiko erhöhen, da der zusätzliche Speicher nur bei Bedarf zugewiesen wird. So weist beispielsweise mysqld nur dann mehr Speicher zu, wenn Sie eine lange Anfrage haben oder wenn mysqld eine große Ergebniszeile zurückgeben muss. Der kleine Standardwert dieser Variablen ist eine Vorsichtsmaßnahme, um unkorrekte Pakete zwischen Client und Server abzufangen und zu gewährleisten, dass Sie keine Speicherplatzprobleme bekommen, weil Sie versehentlich zu große Pakete verwenden.

Es können auch seltsame Dinge mit großen Paketen passieren, wenn Sie umfangreiche `BLOB`-Werte benutzen, aber mysqld zu wenig Speicher gegeben haben, um mit der Anfrage umzugehen. Wenn Sie den Verdacht haben, dass dies der Fall ist, müssen Sie ulimit -d 256000 am Anfang des mysqld_safe-Skripts hinzufügen und mysqld neu starten.

### A.2.10. Kommunikationsfehler/abgebrochene Verbindung

Das Fehlerlog des Servers kann wichtige Informationen über Verbindungsprobleme geben (siehe Abschnitt 5.12.1, „Die Fehler-Logdatei“). Wenn Sie den Server mit der Option `--log-warnings` starten, finden Sie im Fehlerlog vielleicht Meldungen wie diese:

    010301 14:38:23  Aborted connection 854 to db: 'users' user: 'josh'

Wenn `Aborted connections`-Meldungen im Fehlerlog stehen, kann das folgende Ursachen haben:

- Das Clientprogramm hat nicht `mysql_close()` aufgerufen, bevor es endete.

- Der Client hat länger als `wait_timeout` oder `interactive_timeout` Sekunden geschlafen, ohne Requests an den Server zu senden. Siehe Abschnitt 5.2.2, „Server-Systemvariablen“.

- Das Clientprogramm brach plötzlich mitten in einer Datenübertragung ab.

Wenn so etwas geschieht, setzt der Server die Statusvariable `Aborted_clients` herauf.

Bei folgenden Vorfällen inkrementiert der Server die Statusvariable `Aborted_connects`:

- Ein Client hat kein Zugriffsrecht auf die Datenbank.

- Ein Client benutzt ein falsches Passwort.

- Ein Verbindungspaket enthält nicht die richtigen Informationen.

- Es dauert mehr als `connect_timeout` Sekunden, ein Verbindungspaket zu erhalten. Siehe Abschnitt 5.2.2, „Server-Systemvariablen“.

Wenn diese Dinge passieren, kann das bedeuten, dass jemand versucht, in den Server einzudringen!

Andere Gründe für einen Abbruch von Clients oder Verbindungen können sein:

- Verwendung eines Ethernet-Protokolls mit Linux, sowohl Halb- als auch Voll-Duplex. Viele Linux Ethernet-Treiber haben diesen Fehler. Ob der Fehler auch bei Ihnen vorhanden ist, können Sie testen, indem Sie eine große Datei per FTP zwischen dem Client- und dem Servercomputer übertragen. Wenn der Transfer in einer Art Stop-and-Go-Verkehr abläuft, haben Sie ein Linux-Duplex-Syndrom. Die einzige Lösung besteht darin, den Duplex-Modus für Ihre Netzwerkkarte und ihren Hub/Switch immer entweder auf Voll-Duplex oder auf Halb-Duplex einzustellen und anhand der Ergebnisse die geeignetste Einstellung zu ermitteln.

- Ein Problem mit der Thread-Bibliothek, das Unterbrechungen der Lesevorgänge verursacht.

- Ein schlecht konfiguriertes TCP/IP.

- Fehler in Ethernets, Hubs, Switches, Kabeln usw. Diese lassen sich nur durch Ersetzung von Hardware zweifelsfrei diagnostizieren.

- Die Variable `max_allowed_packet` ist zu klein oder Anfragen erfordern mehr Arbeitsspeicher, als Sie für mysqld zugewiesen haben. Siehe Abschnitt A.2.9, „`Packet too large`-Fehler“.

Siehe auch Abschnitt A.2.8, „`MySQL server has gone away`-Fehler“.

### A.2.11. `The table is full`-Fehler

Ein Fehler wegen voller Tabelle kann aus mehreren Gründen auftreten:

- Sie verwenden einen älteren MySQL Server als 3.23 und eine arbeitsspeicherresidente temporäre Tabelle wird größer als `tmp_table_size` Bytes. Um dies zu verhindern, lassen Sie mysqld mithilfe der Option `--tmp_table_size=`val`` die Größe der temporären Tabellen heraufsetzen oder setzen die SQL-Option `SQL_BIG_TABLES`, bevor Sie die problematische Anfrage absetzen. Siehe Abschnitt 13.5.3, „`SET`“.

  Sie können auch mysqld mit der Option `--big-tables` starten. Das ist genau dasselbe, als würden Sie `SQL_BIG_TABLES` für sämtliche Anfragen verwenden.

  Seit MySQL 3.23 sollte dieses Problem erledigt sein. Wenn eine speicherresidente temporäre Tabelle größer als `tmp_table_size` wird, macht sie der Server automatisch zu einer `MyISAM`-Tabelle auf der Festplatte.

- Sie verwenden `InnoDB`-Tabellen und haben keinen Platz mehr im `InnoDB`-Tablespace. In diesem Fall müssen Sie den `InnoDB`-Tablespace vergrößern. Siehe Abschnitt 14.2.7, „Hinzufügen und Entfernen von InnoDB-Daten- und -Logdateien“.

- Sie verwenden `ISAM`- oder `MyISAM`-Tabellen auf einem Betriebssystem, das nur maximal 2 Gbyte große Dateien zulässt, und Ihre Daten- oder Indexdatei übersteigt dieses Limit.

- Sie benutzen eine `MyISAM`-Tabelle, die mehr Platz braucht, als die interne Zeigergröße gestattet. Wenn Sie nicht beim Anlegen der Tabelle die Tabellenoption `MAX_ROWS` gesetzt haben, verwendet MySQL die Systemvariable `myisam_data_pointer_size`. Deren Standardwert beträgt 6 Byte, genug, um 256-Tbyte- Daten zuzulassen. Siehe Abschnitt 5.2.2, „Server-Systemvariablen“.

  Die Größenlimits für Daten- und Indexdatei prüfen Sie mit folgender Anweisung:

      SHOW TABLE STATUS FROM database LIKE 'tbl_name';

  Sie können auch myisamchk -dv /path/to/table-index-file benutzen.

  Ist die Zeigergröße zu klein, können Sie dies mit `ALTER TABLE` ändern:

      ALTER TABLE tbl_name MAX_ROWS=1000000000 AVG_ROW_LENGTH=nnn;

  Den Wert `AVG_ROW_LENGTH` müssen Sie nur für Tabellen mit `BLOB`- oder `TEXT`-Spalten angeben; in diesem Fall kann MySQL den Platzbedarf nicht anhand der Zeilenzahl optimieren.

### A.2.12. `Can't create/write to file`-Fehler

Wenn Sie bei manchen Anfragen den folgenden Fehlertyp ernten, so bedeutet dies, dass MySQL keine temporäre Datei für die Ergebnismenge im temporären Verzeichnis anlegen kann:

    Can't create/write to file '\\sqla3fe_0.ism'.

Dieser Fehler ist typisch für Windows; bei Unix sieht die Meldung ähnlich aus.

Eine Möglichkeit ist die, mysqld mit der Option `--tmpdir` zu starten oder sie in den Abschnitt `[mysqld]` Ihrer Optionsdatei zu schreiben. Um beispielsweise das Verzeichnis `C:\temp` vorzugeben, schreiben Sie:

    [mysqld]
    tmpdir=C:/temp

Das Verzeichnic `C:\temp` muss existieren und genügend Platz bieten, damit der MySQL Server hineinschreiben kann. Siehe Abschnitt 4.3.2, „my.cnf-Optionsdateien“.

Auch Berechtigungsprobleme können den Fehler verursachen. Achten Sie darauf, dass der MySQL Server in das `tmpdir`-Verzeichnis schreiben darf.

Schauen Sie auch auf den Fehlercode, den Ihnen perror liefert. Manchmal kann der Server nicht in eine Tabelle schreiben, weil das Dateisystem voll ist:

    shell> perror 28
    Error code  28:  No space left on device

### A.2.13. `Command out of sync`-Fehler in Client

Wenn `Commands out of sync; you can't run this command now` in Ihrem Clientcode gemeldet wird, rufen Sie Clientfunktionen in der verkehrten Reihenfolge auf.

Dies kann zum Beispiel geschehen, wenn Sie `mysql_use_result()` benutzen und versuchen, eine neue Anfrage auszuführen, ehe Sie `mysql_free_result()` aufgerufen haben. Oder wenn Sie versuchen, zwei Anfragen, die Daten liefern, auszuführen, ohne dazwischen `mysql_use_result()` oder `mysql_store_result()` aufzurufen.

### A.2.14. `User ignored`-Fehler

Wenn Sie folgende Fehlermeldung sehen, so bedeutet dies, dass beim Starten von mysqld oder beim Neuladen der Berechtigungstabellen in der `user`-Tabelle ein Konto mit einem verkehrten Passwort gefunden wurde.

`Found wrong password for user '`some_user`'@'`some_host`'; ignoring user`

Infolgedessen wird das Konto vom Berechtigungssystem einfach ignoriert.

Die folgende Liste zeigt mögliche Ursachen und Lösungen für dieses Problem auf:

- Vielleicht führen Sie eine aktuelle mysqld-Version mit einer alten `user`-Tabelle aus. Führen sie mysqlshow mysql user aus, um zu überprüfen, ob die `Password`-Spalte kürzer als 16 Zeichen ist. Wenn ja, so können Sie dies mit dem Skript `scripts/add_long_password` korrigieren.

- Das Konto hat ein altes Passwort (8 Zeichen lang) und Sie haben mysqld nicht mit der Option `--old-protocol` gestartet. Dann können Sie entweder das Konto in der `user`-Tabelle auf ein neues Passwort umstellen oder mysqld mit der Option `--old-protocol` neu starten.

- Sie haben in der `user`-Tabelle ein Passwort angegeben, ohne die `PASSWORD()`-Funktion zu benutzen. Stellen Sie mit mysql das Konto in der `user`-Tabelle auf ein neues Passwort um und achten Sie darauf, die Funktion `PASSWORD()` zu verwenden:

      mysql> UPDATE user SET Password=PASSWORD('newpwd')
          -> WHERE User='some_user' AND Host='some_host';

### A.2.15. `Table 'xxx' doesn't exist`-Fehler

Wenn Sie eine der folgenden Fehlermeldungen sehen, so bedeutet dies, dass in der voreingestellten Datenbank keine Tabelle mit dem gegebenen Namen existiert:

    Table 'tbl_name' doesn't exist
    Can't find file: 'tbl_name' (errno: 2)

In manchen Fällen ist die Tabelle zwar vorhanden, aber Sie sprechen sie nicht richtig an:

- Da MySQL Datenbanken und Tabellen in Verzeichnissen und Dateien speichert, unterscheiden die Namen der Datenbanken und Tabellen zwischen Groß- und Kleinschreibung, wenn sie in einem Dateisystem vorliegen, das selbst zwischen Groß- und Kleinschreibung unterscheidet.

- Selbst in Dateisystemen, die nicht zwischen Groß- und Kleinschreibung unterscheiden, wie etwa Windows, muss eine Tabelle in einer Anfrage immer gleich geschrieben werden (entweder groß oder klein).

Der Befehl `SHOW TABLES` verrät Ihnen, welche Tabellen in Ihrer Datenbank vorliegen. Siehe Abschnitt 13.5.4, „`SHOW`“.

### A.2.16. `Can't initialize charset xxx`-Fehler

Bei Zeichensatzproblemen kann ein Fehler wie dieser auftreten:

    MySQL Connection Failed: Can't initialize character set charset_name

Dieser Fehler kann folgende Gründe haben:

- Der Zeichensatz ist ein Multibytezeichensatz und in Ihrem Client ist keine Unterstützung dafür vorhanden. In diesem Fall müssen Sie den Client neu kompilieren, indem Sie configure mit der Option `--with-charset=`charset_name`` oder `--with-extra-charsets=`charset_name`` ausführen. Siehe Abschnitt 2.8.2, „Typische configure-Optionen“.

  Alle MySQL-Standardbinaries werden mit der Option `--with-extra-character-sets=complex` kompiliert, die alle Multibytezeichensätze unterstützt. Siehe Abschnitt 5.11.1, „Der für Daten und zum Sortieren benutzte Zeichensatz“.

- Der Zeichensatz ist ein einfacher Zeichensatz, der nicht in mysqld kompiliert ist, und seine Definitionsdateien sind nicht dort, wo der Client sie sucht.

  In diesem Fall können Sie Ihr Problem mit einer der folgenden Methoden lösen:

  - Sie rekompilieren den Client mit Unterstützung für den betreffenden Zeichensatz. Siehe Abschnitt 2.8.2, „Typische configure-Optionen“.

  - Sie geben dem Client das Verzeichnis an, in dem er die Definitionsdateien des Zeichensatzes finden kann. Für viele Clients können Sie dies mit der Option `--character-sets-dir` tun.

  - Sie kopieren die Definitionsdateien des Zeichensatzes in den Pfad, wo der Client sie sucht.

### A.2.17. Datei nicht gefunden

Wenn Sie den Fehler `ERROR '...' not found (errno: 23)`, `Can't open file: ... (errno: 24)` oder einen anderen Fehler mit der `errno 23` oder `errno 24` von MySQL gemeldet bekommen, haben Sie nicht genügend Dateideskriptoren für den MySQL Server zugewiesen. Das Dienstprogramm perror verrät Ihnen, was welche Fehlernummer bedeutet:

    shell> perror 23
    Error code  23:  File table overflow
    shell> perror 24
    Error code  24:  Too many open files
    shell> perror 11
    Error code  11:  Resource temporarily unavailable

Das Problem hierbei ist, dass mysqld versucht, zu viele Dateien gleichzeitig geöffnet zu halten. Sie können entweder mysqld veranlassen, nicht so viele Dateien zugleich zu öffnen, oder die Anzahl der für mysqld verfügbaren Dateideskriptoren erhöhen.

Damit mysqld weniger Dateien zugleich offen behält, können Sie den Tabellen-Cache verkleinern, indem Sie den Wert der Systemvariablen `table_open_cache` heruntersetzen (ihr Standardwert ist 64). Wenn Sie die `max_connections` vermindern, vermindern Sie in einem auch die Anzahl der offenen Dateien (der Standardwert beträgt 100).

Die Anzahl der für mysqld verfügbaren Dateideskriptoren ändern Sie mit der Option `--open-files-limit` für mysqld_safe, oder Sie setzen (seit MySQL 3.23.30) die Systemvariable `open_files_limit`. Siehe Abschnitt 5.2.2, „Server-Systemvariablen“. Am einfachsten können Sie diese Werte ändern, indem Sie eine Option in Ihrer Optionsdatei einstellen. Siehe Abschnitt 4.3.2, „my.cnf-Optionsdateien“. Wenn Sie eine ältere Version von mysqld verwenden, in der sich die Höchstzahl der offenen Dateien nicht einstellen lässt, können Sie das Skript mysqld_safe bearbeiten. Dort gibt es eine auskommentierte Zeile mit dem Inhalt ulimit -n 256. Daraus entfernen Sie das Kommentarzeichen ‘`#`’ und stellen die Zahl `256` auf die Anzahl der gewünschten Dateideskriptoren um, die mysqld zur Verfügung stehen sollen.

`--open-files-limit` und ulimit können zwar die Anzahl der Dateideskriptoren erhöhen, aber nur bis zu dem Limit, das für Ihr Betriebssystem zulässig ist. Außerdem gibt es ein „hartes“ Limit, das nur überschrieben werden kann, wenn Sie mysqld_safe oder mysqld als `root` starten (denken Sie aber daran, in diesem Fall den Server mit der `--user`-Option zu starten, damit er nicht nach dem Hochfahren als `root` weiterläuft). Wenn Sie das Betriebssystemlimit für die Anzahl der Dateideskriptoren, die für jeden Prozess verfügbar sind, ändern möchten, müssen Sie in Ihre Systemdokumentation schauen.

Hinweis: Wenn Sie die tcsh-Shell ausführen, funktioniert ulimit nicht! Außerdem meldet tcsh verkehrte Werte, wenn Sie nach den aktuellen Limits fragen. In diesem Fall sollten Sie mysqld_safe mit sh starten.

## A.3. Installationsbezogene Themen

### A.3.1. Probleme beim Linken mit der MySQL-Clientbibliothek

Wenn Sie ein Anwendungsprogramm so verlinken, dass es die MySQL-Clientbibliothek benutzt, werden für Symbole, die mit `mysql_` anfangen, `undefined reference`-Fehler gemeldet werden:

    /tmp/ccFKsdPa.o: In function `main':
    /tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init'
    /tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect'
    /tmp/ccFKsdPa.o(.text+0x57): undefined reference to `mysql_real_connect'
    /tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error'
    /tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'

Um dieses Problem zu lösen, fügen Sie am Ende Ihres Link-Befehls `-Ldir_path -lmysqlclient` an, wobei `dir_path` den Pfadnamen des Verzeichnisses darstellt, in dem die Clientbibliothek liegt. Mit folgendem Befehl können Sie das richtige Verzeichnis herausfinden:

    shell> mysql_config --libs

Die Ausgabe von mysql_config kann auch auf andere Bibliotheken hinweisen, die ebenfalls im Link-Befehl angegeben werden sollten.

Wenn `undefined reference`-Fehler für die Funktion `uncompress` oder `compress` gemeldet werden, fügen Sie am Ende des Link-Befehls `-lz` an und versuchen es erneut.

Treten `undefined reference`-Fehler im Zusammenhang mit einer Funktion auf, die auf Ihrem System existieren müsste, wie beispielsweise `connect`, sehen Sie auf der Handbuchseite zu dieser Funktion nach, um festzustellen, welche Bibliotheken Sie im Link-Befehl angeben müssen.

Wenn Funktionen auf Ihrem System nicht existieren, werden `undefined reference`-Fehler wie diese gemeldet:

    mf_format.o(.text+0x201): undefined reference to `__lxstat'

Das bedeutet normalerweise, dass Ihre MySQL-Clientbibliothek auf einem System kompiliert wurde, das mit Ihrem nicht zu 100 % kompatibel ist. In diesem Fall sollten Sie die neueste MySQL-Quelldistribution herunterladen und MySQL selbst kompilieren. Siehe Abschnitt 2.8, „Installation der Quelldistribution“.

Zur Laufzeit können `undefined reference`-Fehler auftreten, wenn Sie versuchen, ein MySQL-Programm auszuführen. Wenn diese Fehler Symbole betreffen, die mit `mysql_` anfangen oder anzeigen, dass die `mysqlclient`-Bibliothek nicht zu finden ist, so bedeutet dies, dass Ihr System die Shared Library `libmysqlclient.so` nicht finden kann. Dies beheben Sie, indem Sie Ihr System dort, wo sich die Bibliothek befindet, nach Shared Libraries suchen lassen. Aus den folgenden Verfahren können Sie das für Ihr System geeignete auswählen:

- Sie fügen den Pfad zu dem Verzeichnis, in dem `libmysqlclient.so` liegt, der Umgebungsvariablen `LD_LIBRARY_PATH` hinzu.

- Sie fügen den Pfad zu dem Verzeichnis, in dem `libmysqlclient.so` liegt, der Umgebungsvariablen `LD_LIBRARY` hinzu.

- Sie kopieren `libmysqlclient.so` in ein Verzeichnis, in dem Ihr System nachschaut, wie beispielsweise `/lib`, und aktualisieren die Shared Library-Informationen, indem Sie `ldconfig` ausführen.

Sie können dieses Problem auch angehen, indem Sie Ihr Programm statisch mit der Option `-static` verlinken oder indem Sie die dynamischen MySQL-Bibliotheken entfernen, bevor Sie Ihren Code verlinken. Ehe Sie die zweite Methode wählen, müssen Sie sich vergewissern, dass keine anderen Programme die dynamischen Bibliotheken benutzen.

### A.3.2. Probleme mit Dateirechten

Wenn Sie Probleme mit Dateiberechtigungen haben, ist vielleicht die Umgebungsvariable `UMASK` beim Starten von mysqld falsch gesetzt. So könnte MySQL beispielsweise folgende Fehlermeldung ausgeben, wenn Sie eine Tabelle anlegen:

    ERROR: Can't find file: 'path/with/filename.frm' (Errcode: 13)

Der Standardwert von `UMASK` ist `0660`. Dies können Sie ändern, indem Sie mysqld_safe folgendermaßen starten:

    shell> UMASK=384  # = 600 in octal
    shell> export UMASK
    shell> mysqld_safe &

Nach Voreinstellung legt MySQL Datenbanken und `RAID`-Verzeichnisse mit dem Zugriffsberechtigungswert `0700` an. Dies können Sie ändern, indem Sie die Variable `UMASK_DIR` einstellen. Wenn Sie ihren Standardwert ändern, werden neue Verzeichnisse mit einer Kombination der Werte `UMASK` und `UMASK_DIR` angelegt. Wenn Sie beispielsweise Gruppenzugriff für alle neuen Verzeichnisse festlegen möchten, gehen Sie folgendermaßen vor:

    shell> UMASK_DIR=504  # = 770 in octal
    shell> export UMASK_DIR
    shell> mysqld_safe &

In der Version 3.23.25 und höher geht MySQL von einem Oktalwert für `UMASK` und `UMASK_DIR` aus, wenn der Wert mit einer Null beginnt.

Siehe Anhang F, Umgebungsvariablen.

## A.4. Administrationsbezogene Themen

### A.4.1. Wie ein vergessenes Kennwort zurückgesetzt wird

Wenn Sie niemals ein `root`-Passwort für MySQL gesetzt haben, verlangt der Server überhaupt kein Passwort für eine `root`-Verbindung. Allerdings empfehlen wir Ihnen dringend, für jedes Konto ein Passwort einzurichten. Siehe Abschnitt 5.7.1, „Allgemeine Sicherheitsrichtlinien“.

Wenn Sie ein `root`-Passwort eingerichtet hatten, aber sich nicht mehr daran erinnern können, müssen Sie es neu einstellen. Die nachfolgende Anleitung ist auf Windows zugeschnitten; eine entsprechende Anleitung für Unix-Systeme finden Sie weiter unten in diesem Abschnitt.

Vorgehen unter Windows:

1. Sie melden sich als Administrator an.

2. Sie halten den MySQL Server an, falls er läuft. Läuft er als Windows-Dienst, müssen Sie dazu den Dienstmanager verwenden:

       Start -> Systemsteuerung -> Verwaltung -> Dienste

   Suchen Sie in der Dienstliste den MySQL-Dienst und halten Sie ihn an.

   Wenn Ihr Server nicht als Dienst läuft, müssen Sie eventuell den Task-Manager einschalten, um ihn mit Gewalt zu stoppen.

3. Legen Sie eine Textdatei an und schreiben Sie folgenden Befehl auf einer einzigen Zeile hinein:

       SET PASSWORD FOR 'root'@'localhost' = PASSWORD('MyNewPassword');

   Speichern Sie die Datei unter einem beliebigen Namen. In diesem Beispiel nennen wir sie `C:\mysql-init.txt`.

4. Öffnen Sie ein Konsolenfenster mit der DOS-Eingabeaufforderung:

       Start -> Ausführen -> cmd

5. Wir gehen davon aus, dass Sie MySQL in `C:\mysql` installiert haben. Wenn nicht, müssen Sie die folgenden Befehle entsprechend abändern.

   Führen Sie an der Eingabeaufforderung folgenden Befehl aus:

       C:\> C:\mysql\bin\mysqld-nt --init-file=C:\mysql-init.txt

   Der Inhalt der in der Option `--init-file` angegebenen Datei wird beim Serverstart ausgeführt, sodass das `root`-Wort geändert wird. Nachdem der Server hochgefahren ist, sollten Sie `C:\mysql-init.txt` löschen.

   Wenn Sie MySQL mit dem MySQL Installation Wizard installieren, müssen Sie unter Umständen die Option `--defaults-file` angeben:

       C:\> "C:\Programme\MySQL\MySQL Server 5.1\bin\mysqld-nt.exe"
                --defaults-file="C:\Program Files\MySQL\MySQL Server 5.1\my.ini"
                --init-file=C:\mysql-init.txt

   Die passende Einstellung für `--defaults-file` finden Sie mithilfe des Dienstmanagers:

       Start -> Systemsteuerung -> Verwaltung -> Dienste

   Suchen Sie den MySQL-Dienst, klicken Sie ihn mit rechts an und wählen Sie `Eigenschaften`. Das Feld `Pfad zur EXE-Datei` enthält die Einstellung für `--defaults-file`.

6. Halten Sie den MySQL Server an und starten Sie ihn dann im Normalmodus neu. Wenn Sie den Server als Dienst betreiben, starten Sie ihn im Dienste-Fenster von Windows; wenn Sie ihn manuell betreiben, starten Sie ihn mit dem Befehl, den Sie auch sonst immer benutzen.

7. Nun müssten Sie mit dem neuen Passwort eine Verbindung bekommen können.

In einer Unix-Umgebung stellen Sie das `root`-Passwort folgendermaßen um:

1. Sie melden sich als Unix- `root`-User oder als der Benutzer, unter dem der mysqld-Server läuft, an.

2. Sie suchen die `.pid`-Datei, welche die Prozess-ID des Servers enthält. Wo sie liegt und wie sie heißt, hängt von Ihrer Distribution, Ihrem Hostnamen und Ihrer Konfiguration ab. Gebräuchliche Speicherorte sind zum Beispiel `/var/lib/mysql/`, `/var/run/mysqld/` und `/usr/local/mysql/data/`. Im Allgemeinen hat der Dateiname die Erweiterung `.pid` und fängt entweder mit `mysqld` oder dem Hostnamen Ihres Systems an.

   Sie können den MySQL Server anhalten, indem Sie einen normalen `kill`-Befehl (nicht `kill -9`) an den mysqld-Prozess übermitteln und dabei den Pfadnamen der `.pid`-Datei angeben:

       shell> kill `cat /mysql-data-directory/host_name.pid`

   Beachten Sie, dass wir Backticks anstelle von Anführungszeichen für den `cat`-Befehl benutzen. Sie sorgen dafür, dass die Ausgabe von `cat` in den `kill`-Befehl eingesetzt wird.

3. Legen Sie eine Textdatei an und schreiben Sie folgenden Befehl auf einer einzigen Zeile hinein:

       SET PASSWORD FOR 'root'@'localhost' = PASSWORD('MyNewPassword');

   Speichern Sie die Datei unter einem beliebigen Namen. In diesem Beispiel heißt sie `~/mysql-init`.

4. Starten Sie den MySQL Server mit der Spezialoption `--init-file=~/mysql-init`:

       shell> mysqld_safe --init-file=~/mysql-init &

   Der Inhalt der init-Datei wird beim Serverstart ausgeführt und ändert das Root-Passwort. Nachdem der Server hochgefahren ist, sollten Sie `~/mysql-init` löschen.

5. Nun müsste das neue Passwort funktionieren.

Alternativ können Sie das neue Passwort auf jeder Plattform auch mit dem Client mysql einstellen (aber diese Methode ist nicht so sicher):

1. Halten Sie mysqld an und starten Sie ihn erneut mit den Optionen `--skip-grant-tables --user=root` (Windows-Nutzer lassen `--user=root` weg).

2. Verbinden Sie sich mit folgendem Befehl mit dem mysqld-Server:

       shell> mysql -u root

3. Geben Sie im mysql-Client folgende Anweisungen:

       mysql> UPDATE mysql.user SET Password=PASSWORD('newpwd')
           ->                   WHERE User='root';
       mysql> FLUSH PRIVILEGES;

   Ersetzen Sie „`newpwd`“ durch das `root`-Passwort, das Sie in Wirklichkeit benutzen möchten.

4. Das neue Passwort sollte nun funktionieren.

### A.4.2. Was zu tun ist, wenn MySQL andauernd abstürzt

Jede MySQL-Version wird vor dem Release auf vielen Plattformen getestet. Dennoch kann es immer noch Bugs in MySQL geben, allerdings ziemlich wenige, die darüber hinaus schwer zu finden sind. Wenn Sie ein Problem haben, ist es immer gut, ganz genau festzustellen, was Ihr System zum Absturz brachte. Dann sind Ihre Chancen auf schnelle Abhilfe viel besser.

Als Erstes müssen Sie herausfinden, ob Ihr mysqld-Server oder Ihr Client an dem Absturz schuld ist. Der Befehl mysqladmin version verrät Ihnen, wie lange Ihr mysqld-Server bereits läuft. Wenn mysqld herunter- und wieder hochgefahren ist, finden Sie die Wurzel des Problems vielleicht im Fehlerlog des Servers. Siehe Abschnitt 5.12.1, „Die Fehler-Logdatei“.

Auf manchen Systemen enthält das Fehlerlog einen Stack-Trace mit der Information, wo mysqld abgestürzt ist. Diesen Trace können Sie mit dem Programm `resolve_stack_dump` auswerten. Siehe Abschnitt E.1.4, „Einen Stack-Trace benutzen“. Beachten Sie, dass die Variablenwerte im Fehlerlog nicht immer hundertprozentig korrekt sind.

Viele Serverabstürze werden durch beschädigte Daten- oder Indexdateien verursacht. MySQL aktualisiert nach jeder SQL-Anweisung und vor der Benachrichtigung des Clients über das Ergebnis die Dateien auf der Festplatte mit dem Systemaufruf `write()`. (Das gilt allerdings nicht, wenn Sie mit der Option `--delay-key-write` arbeiten: Hier werden zwar die Datendateien zeitnah geschrieben, aber nicht die Indexdateien.) Das bedeutet, dass der Inhalt der Datendateien selbst bei einem mysqld-Absturz sicher ist, weil das Betriebssystem dafür sorgt, dass die Arbeitsspeicherdaten auf die Platte zurückgeschrieben werden. Sie können MySQL zwingen, nach jeder SQL-Anweisung gleich alles auf die Platte zurückzuschreiben, indem Sie mysqld mit der Option `--flush` starten.

Das bedeutet, dass Sie normalerweise nur in folgenden Fällen mit beschädigten Tabellen zu tun haben:

- Wenn der MySQL Server oder der Serverhost mitten in einem Update abgestürzt ist.

- Wenn Sie einen Bug in mysqld gefunden haben, der den Prozess mitten in einem Update anhielt.

- Wenn ein externes Programm Daten- oder Indexdateien zur gleichen Zeit wie mysqld ändert, ohne die Tabelle ordentlich zu sperren.

- Wenn Sie viele mysqld-Server zugleich mit demselben Data Directory auf einem System betreiben, das keine vernünftigen Dateisystemsperren kennt (diese werden normalerweise von dem Sperrenmanager `lockd` verwaltet), oder wenn Sie mehrere Server bei ausgeschaltetem externem Locking laufen lassen.

- Wenn Sie eine abgestürzte Daten- oder Indexdatei mit völlig kaputten Daten haben, die mysqld in Verwirrung stürzt.

- Wenn Sie einen Fehler im Code der Datenspeicherung gefunden haben. Das ist zwar unwahrscheinlich, aber nicht unmöglich. In diesem Fall können Sie versuchen, die Speicher-Engine auf eine andere Engine umzustellen, indem Sie `ALTER TABLE` auf einer reparierten Kopie der Tabelle ausführen.

Da der Grund für einen Absturz so schwer festzustellen ist, sollten Sie zuerst versuchen, herauszufinden, ob Dinge, die bei anderen funktionieren, bei Ihnen abstürzen. Hierzu sollten Sie Folgendes ausprobieren:

- Halten Sie den mysqld-Server mit mysqladmin shutdown an, führen Sie im Data Directory myisamchk --silent --force */*.MYI aus, um alle `MyISAM`-Tabellen zu prüfen, und starten Sie mysqld erneut. Dann ist gewährleistet, dass der Server in einem sauberen Zustand läuft. Siehe Kapitel 5, Datenbankverwaltung.

- Starten Sie mysqld mit der Option `--log` und versuchen Sie, an den Logdaten zu erkennen, ob eine spezifische Anfrage den Server abstürzen lässt. Rund 95 % aller Fehler hängen mit einer konkreten Anfrage zusammen. Normalerweise ist dies eine der letzten Anfragen, die in der Logdatei kurz vor dem Neustart des Servers protokolliert sind. Siehe auch Abschnitt 5.12.2, „Die allgemeine Anfragen-Logdatei“. Wenn Sie MySQL mit einer bestimmten Anfrage wiederholt zum Absturz bringen können, obwohl Sie alle Tabellen kurz vorher überprüft haben, dann haben Sie den Fehler gefunden und sollten einen Bugreport übermitteln. Siehe hierzu Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.

- Versuchen Sie, einen Testfall einzurichten, den wir verwenden können, um den Fehler zu reproduzieren. Siehe Abschnitt E.1.6, „Erzeugen eines Testfalls, wenn Sie Tabellenbeschädigung feststellen“.

- Versuchen Sie, die Tests im Verzeichnis `mysql-test` und die MySQL-Benchmarks auszuführen. Siehe Abschnitt 26.1.2, „MySQL-Testsystem“. Damit sollte MySQL ziemlich gut getestet sein. Sie können den Benchmarks auch Code hinzufügen, der Ihre Anwendung simuliert. Die Benchmarks finden Sie im Verzeichnis `sql-bench` einer Quelldistribution oder im Verzeichnis `sql-bench` unterhalb des MySQL-Installationsverzeichnisses in einer Binärdistribution.

- Probieren Sie es mit dem Skript `fork_big.pl`. (Dieses finden Sie im Verzeichnis `tests` der Quelldistributionen.)

- Wenn Sie MySQL für das Debugging konfigurieren, lassen sich Informationen über mögliche Fehler viel leichter beschaffen. In der Debuggingkonfiguration ist eine Arbeitsspeicherzuweisung enthalten, die so manchem Fehler auf die Spur kommt. Außerdem liefert diese Konfiguration viele Ausgabedaten über alles, was vor sich geht. Rekonfigurieren Sie also MySQL mit der Option `--with-debug` oder `--with-debug=full` für configure und kompilieren Sie dann neu. Siehe auch Abschnitt E.1, „Einen MySQL-Server debuggen“.

- Installieren Sie immer die neuesten Patches für Ihr Betriebssystem.

- Stellen Sie die Option `--skip-external-locking` für mysqld ein. Auf manchen Systemen funktioniert der Sperrenmanager `lockd` nicht richtig. Die Option `--skip-external-locking` hält mysqld davon ab, externes Locking zu benutzen. (Das bedeutet, dass Sie nicht zwei mysqld-Server mit demselben Data Directory betreiben können und dass Sie mit myisamchk aufpassen müssen. Aber immerhin kann es sehr aufschlussreich sein, die Option einmal auszuprobieren.)

- Haben Sie es schon mit mysqladmin -u root processlist versucht, wenn mysqld scheinbar läuft, aber nicht antwortet? Manchmal ist mysqld gar nicht ins Koma gefallen, auch wenn es den Anschein hat. Vielleicht sind alle Verbindungen belegt oder es gibt ein Problem mit internen Sperren. Normalerweise kann mysqladmin -u root processlist selbst in solchen Fällen eine Verbindung einrichten und Aufschluss über die Anzahl und den Status der laufenden Verbindungen geben.

- Führen Sie in einem separaten Fenster den Befehl mysqladmin -i 5 status oder mysqladmin -i 5 -r status aus, um Statistiken zu erstellen, während sie andere Anfragen ausführen.

- Versuchen Sie Folgendes:

  1. Starten Sie mysqld von gdb (oder einem anderen Debugger) aus. Siehe auch Abschnitt E.1.3, „mysqld unter gdb debuggen“.

  2. Lassen Sie Ihre Testskripten laufen.

  3. Geben Sie den Backtrace und die lokalen Variablen auf den drei untersten Ebenen aus. In gdb tun Sie dies mit den folgenden Befehlen, wenn mysqld innerhalb von gdb abgestürzt ist:

         backtrace
         info local
         up
         info local
         up
         info local

     In gdb können Sie auch mit `info threads` herausfinden, welche Threads vorhanden sind, und mit `thread `N`` auf einen bestimmten Thread umschalten, wobei `N` die Thread-ID ist.

- Versuchen Sie, Ihre Anwendung mit einem Perl-Skript zu simulieren, um MySQL zu einem Absturz oder Fehlverhalten zu veranlassen.

- Senden Sie einen normalen Bugreport. Siehe Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“. Machen Sie noch detailliertere Angaben als üblich. Da MySQL bei den meisten Nutzern funktioniert, kann es sein, dass der Crash durch Umstände verursacht wird, die nur auf Ihrem Compter existieren (zum Beispiel im Zusammenhang mit Ihren Systembibliotheken).

- Wenn Sie Schwierigkeiten mit Tabellen haben, die Datenzeilen mit variabler Länge speichern und nur `VARCHAR`-, aber keine `BLOB`- oder `TEXT`-Spalten benutzen, können Sie mit `ALTER TABLE` ausprobieren, alle `VARCHAR`- in `CHAR`-Spalten zu ändern. Damit zwingen Sie MySQL, Zeilen mit fester Länge zu verwenden, die zwar ein bisschen mehr Platz belegen, aber weniger anfällig für Beschädigungen sind.

  Der jetzige Code für dynamische Zeilen, den MySQL AB schon seit Jahren verwendet, macht nur minimale Probleme, aber Zeilen dynamischer Länge sind von Natur aus fehleranfälliger. Daher sollten Sie bei Problemen folgende Strategie versuchen:

- Beziehen Sie auch Ihre Serverhardware als mögliche Fehlerursache ein. Auch Hardwaredefekte können Datenkorruption verursachen. Achten Sie bei der Hardware besonders auf RAMs und Festplattenlaufwerke.

### A.4.3. Wie MySQL mit vollen Festplatten umgeht

Dieser Abschnitt beschreibt, wie MySQL mit Fehlern umgeht, die aufgrund einer vollen Festplatte auftreten (wie beispielsweise „no space left on device“), und wie Fehler aufgrund von Kontingentüberschreitung behandelt werden (wie zum Beispiel „write failed“ oder „user block limit reached“).

Dieser Abschnitt ist für Schreiboperationen auf `MyISAM`-Tabellen relevant. Er gilt jedoch auch für Schreiboperationen in Binärlogdateien und die Binärlog-Indexdatei, nur dass die Begriffe „row“ und „record“ im Zusammenhang mit Logs „Ereignisse“ bedeuten.

Wenn ein Fehler wegen voller Festplatte auftritt, geht MySQL wie folgt vor:

- Es prüft einmal pro Minute, ob genug Platz vorhanden ist, um die aktuelle Zeile zu schreiben. Wenn dies der Fall ist, macht es weiter, als sei nichts geschehen.

- Alle 10 Minuten schreibt es in die Logdatei eine Warnung, dass die Festplatte voll ist.

Dieses Problem können Sie folgendermaßen beheben:

- Um weiterarbeiten zu können, müssen Sie lediglich genug Platz auf der Platte schaffen, um alle Datensätze zu schreiben.

- Um den Thread anzuhalten, sagen Sie mysqladmin kill. Dann wird der Thread das nächste Mal, wenn er die Platte überprüft (also in einer Minute), gestoppt.

- Eventuell warten andere Threads auf die Tabelle, welche die Fehlerbedingung `disk-full` verursacht hat. Wenn Sie mehrere „gesperrte“ Threads haben, können nach Abbruch des einen Threads, der wegen der `disk-full`-Bedingung wartet, die anderen Threads weiterlaufen.

Das oben geschilderte Verhalten tritt nicht ein, wenn Sie `REPAIR TABLE` oder `OPTIMIZE TABLE` gesagt haben oder wenn die Indizes nach `LOAD DATA INFILE` oder nach einer `ALTER TABLE`-Anweisung in Stapelverarbeitung erstellt werden. Alle diese Anweisungen können große temporäre Dateien erzeugen, die den Rest des Systems in Schwierigkeiten bringen, wenn sie sich selbst überlassen bleiben. Wenn die Platte voll läuft, während MySQL eine dieser Operationen ausführt, löscht MySQL eine der großen temporären Dateien und kennzeichnet die Tabelle als abgestürzt. Ausnahme: Bei `ALTER TABLE` bleibt die alte Tabelle unverändert.

### A.4.4. Wohin MySQL temporäre Dateien speichert

MySQL verwendet den Wert der Umgebungsvariablen `TMPDIR` als Pfad zu dem Verzeichnis, in dem die temporären Dateien gespeichert werden. Wenn Sie `TMPDIR` nicht eingestellt haben, benutzt MySQL den systemeigenen Standardwert, also normalerweise `/tmp`, `/var/tmp` oder `/usr/tmp`. Wenn das Dateisystem, in dem Ihr Verzeichnis für temporäre Dateien liegt, zu klein ist, können Sie mit der Option `--tmpdir` von mysqld ein anderes Verzeichnis in einem ausreichend großen Dateisystem einstellen.

In MySQL 5.1 kann die Option `--tmpdir` auf eine Liste mit mehreren Pfaden eingestellt werden, die dann im Ringverfahren (jeder kommt einmal dran) benutzt werden. Die Pfade sollten auf Unix durch Doppelpunkte (‘`:`’) getrennt werden, und auf Windows, NetWare und OS/2 durch Semikola (‘`;`’). Hinweis: Um die Last wirkungsvoll zu verteilen, sollten diese Pfade zu verschiedenen physikalischen Platten und nicht nur zu verschiedenen Partitionen derselben Festplatte führen.

Wenn der MySQL Server ein Replikationsslave ist, sollten Sie die Option `--tmpdir` nicht auf ein Verzeichnis in einem arbeitsspeicherbasierten Dateisystem oder auf ein anderes Verzeichnis einstellen, das beim Neustart des Serverhosts gelöscht wird. Ein Replikationsslave benötigt einige seiner temporären Dateien, um einen Neustart des Computers so zu überleben, dass er temporäre Tabellen oder `LOAD DATA INFILE`-Operationen replizieren kann. Wenn Dateien aus dem temporären Verzeichnis beim Neustart des Servers verloren gehen, scheitert die Replikation.

MySQL legt alle temporären Dateien als verborgene Dateien an. Das soll gewährleisten, dass die temporären Dateien beim Herunterfahren von mysqld entfernt werden. Allerdings haben verborgene Dateien den Nachteil, dass eine große temporäre Datei, die das Dateisystem überlastet, in welchem das temporäre Verzeichnis liegt, nicht zu sehen ist.

Bei Sortieroperationen (`ORDER BY` oder `GROUP BY`) verwendet MySQL normalerweise ein oder zwei temporäre Dateien. Wie viel Platz auf der Festplatte dafür maximal notwendig ist, verrät Ihnen der folgende Ausdruck:

    (Länge der Daten + sizeof(Zeilenzeiger))
    * Anzahl der gefundenen Zeilen
    * 2

Der Zeilenzeiger ist normalerweise 4 Byte groß, kann aber bei sehr großen Tabellen in Zukunft noch wachsen.

Für manche `SELECT`-Anfragen legt MySQL ebenfalls temporäre SQL-Tabellen an. Diese sind nicht verborgen und haben Namen der Form `SQL_*`.

`ALTER TABLE` legt eine temporäre Tabelle in dem Verzeichnis der Originaltabelle an.

### A.4.5. Wie Sie die MySQL-Socketdatei `/tmp/mysql.sock` schützen oder ändern

Die Unix-Socketdatei, die der Server für die Kommunikation mit lokalen Clients benötigt, liegt nach Voreinstellung unter `/tmp/mysql.sock`. (In manchen Distributionsformaten kann es auch ein anderes Verzeichnis sein, wie beispielsweise `/var/lib/mysql` für RPMs.)

Auf manchen Unix-Versionen kann jeder Dateien aus dem Verzeichnis `/tmp` oder anderen ähnlichen Verzeichnissen für temporäre Dateien löschen. Wenn die Socketdatei auf Ihrem Dateisystem in einem solchen Verzeichnis liegt, kann das zu Problemen führen.

Auf den meisten Unix-Versionen können Sie Ihr `/tmp`-Verzeichnis schützen, sodass die Dateien nur von ihren Eigentümern oder dem Superuser (`root`) gelöscht werden können. Hierzu setzen Sie das `sticky`-Bit auf dem `/tmp`-Verzeichnis, indem Sie sich als `root` anmelden und folgenden Befehl geben:

    shell> chmod +t /tmp

Ob das `sticky`-Bit gesetzt wurde, prüfen Sie mit `ls -ld /tmp`. Wenn das letzte Zeichen der Berechtigung ein `t` ist, wurde das Bit gesetzt.

Sie können auch veranlassen, dass der Server die Unix-Socketdatei in einem anderen Verzeichnis erstellt. Wenn Sie dies tun, müssen Sie den Clientprogrammen auch verraten, wo diese Datei jetzt liegt. Den Speicherort können Sie auf mehrere Weisen angeben:

- Sie geben den Pfad in einer globalen oder lokalen Optionsdatei an, zum Beispiel indem Sie folgende Zeilen in `/etc/my.cnf` speichern:

      [mysqld]
      socket=/path/to/socket

      [client]
      socket=/path/to/socket

  Siehe Abschnitt 4.3.2, „my.cnf-Optionsdateien“.

- Sie geben auf der Kommandozeile für mysqld_safe und beim Ausführen von Clientprogrammen eine `--socket`-Option an.

- Sie stellen die Umgebungsvariable `MYSQL_UNIX_PORT` auf den Pfad zur Unix-Socketdatei ein.

- Sie rekompilieren MySQL aus den Quelldateien so, dass ein anderer Standardspeicherort für die Unix-Socketdatei festgelegt wird. Den Dateipfad definieren Sie mit der Option `--with-unix-socket-path`, wenn Sie configure ausführen. Siehe auch Abschnitt 2.8.2, „Typische configure-Optionen“.

Ob der neue Socketspeicherort funktioniert, können Sie überprüfen, indem Sie mit folgendem Befehl eine Serververbindung herstellen:

    shell> mysqladmin --socket=/path/to/socket version

### A.4.6. Probleme mit Zeitzonen

Wenn Sie das Problem haben, dass `SELECT NOW()` Werte in UTC anstelle Ihrer Ortszeit liefert, müssen Sie Ihren Server auf Ihre Zeitzone einstellen. Dasselbe gilt, wenn `UNIX_TIMESTAMP()` den verkehrten Wert zurückgibt. Dies sollte für die Umgebung veranlasst werden, in welcher der Server läuft, also zum Beispiel in mysqld_safe oder mysql.server. Siehe Anhang F, Umgebungsvariablen.

Die Zeitzone für den Server stellen Sie mit der Option `--timezone=`timezone_name`` von mysqld_safe ein. Alternativ können Sie die Umgebungsvariable `TZ` einstellen, bevor Sie mysqld starten.

Die zulässigen Werte für `--timezone` oder `TZ` hängen vom System ab. Bitte schlagen Sie in der Dokumentation Ihres Betriebssystems die jeweils passenden Werte nach.

## A.5. Anfragenbezogene Themen

### A.5.1. Groß-/Kleinschreibung beim Suchen

Nach Voreinstellung unterscheiden Suchoperationen in MySQL nicht zwischen Groß- und Kleinschreibung (wobei allerdings manche Zeichensätze grundsätzlich immer zwischen Groß- und Kleinschreibung unterscheiden, wie beispielsweise `czech`). Das bedeutet, dass Sie bei einer Suche mit ``col_name` LIKE 'a%'` alle Spaltenwerte geliefert bekommen, die mit `A` oder `a` anfangen. Wenn Sie diese Suche auf Groß- oder Kleinbuchstaben einschränken möchten, müssen Sie dafür sorgen, dass die Kollation eines der beiden Operanden Groß- und Kleinschreibung unterscheidet oder eine Binärkollation ist. Wenn Sie beispielsweise eine Spalte und einen String vergleichen, die beide den Zeichensatz `latin1` verwenden, können Sie den `COLLATE`-Operator einschalten, um einem der beiden Operanden die Kollation `latin1_general_cs` oder `latin1_bin` zuzuweisen. Zum Beispiel:

    col_name COLLATE latin1_general_cs LIKE 'a%'
    col_name LIKE 'a%' COLLATE latin1_general_cs
    col_name COLLATE latin1_bin LIKE 'a%'
    col_name LIKE 'a%' COLLATE latin1_bin

Wenn Sie in einer Spalte immer die Groß- und Kleinschreibung berücksichtigen möchten, deklarieren Sie sie mit einer Binärkollation oder CS-Kollation (CS steht für die Unterscheidung von Groß- und Kleinschreibung). Siehe Abschnitt 13.1.5, „`CREATE TABLE`“.

Einfache Vergleichsoperationen (`>=, >, =, <, <=`, Sortieren und Gruppieren) beruhen auf dem „Sortierwert“ der Zeichen. Zeichen mit demselben Sortierwert (wie etwa ‘`E`’, ‘`e`’ und ‘`Ã©`’) werden als gleich betrachtet.

### A.5.2. Probleme bei der Benutzung von `DATE`-Spalten

Das Format eines `DATE`-Werts ist `'YYYY-MM-DD'`. Im Standard-SQL ist kein anderes Format erlaubt. Dieses Format muss in `UPDATE`-Ausdrücken und in der `WHERE`-Klausel von `SELECT`-Anweisungen immer verwendet werden. Zum Beispiel:

    mysql> SELECT * FROM tbl_name WHERE date >= '2003-05-05';

Der Bequemlichkeit halber konvertiert MySQL ein Datum, das in einem numerischen Kontext benutzt wird, automatisch in eine Zahl (und umgekehrt). MySQL ist auch clever genug, um bei Updates und in einer `WHERE`-Klausel, die ein Datum mit einer `TIMESTAMP`-, `DATE`- oder `DATETIME`-Spalte vergleicht, eine „lockere“-String-Form zuzulassen. („Lockere Form“ bedeutet, dass zwischen den einzelnen Teilen jedes Interpunktionszeichen als Trennzeichen zulässig ist. So sind zum Beispiel `'2004-08-15'` und `'2004#08#15'` äquivalent.) MySQL kann auch einen String, der keine Trennzeichen enthält (wie etwa `'20040815'`) konvertieren, vorausgesetzt, er ergibt einen vernünftigen Datumswert.

Wenn Sie Werte vom Typ `DATE`, `TIME`, `DATETIME` oder `TIMESTAMP` mit einem konstanten String vergleichen, der die Operatoren `<`, `<=`, `=`, `>=`, `>` oder `BETWEEN` enthält, konvertiert MySQL den String normalerweise intern in einen langen Integer, um Vergleiche schneller ausführen zu können (und ein wenig „locker“ bei der String-Prüfung sein zu können). Von dieser Konvertierung gibt es allerdings folgende Ausnahmen:

- wenn Sie zwei Spalten vergleichen

- wenn Sie eine `DATE`-, `TIME`-, `DATETIME`- oder `TIMESTAMP`-Spalte mit einem Ausdruck vergleichen

- wenn Sie eine andere Vergleichsmethode als die oben aufgeführten verwenden, wie etwa `IN` oder `STRCMP()`

In diesen Ausnahmefällen führt MySQL den Vergleich durch, indem es die Objekte in Strings konvertiert und dann die Strings vergleicht.

Um sicherzugehen, sollten Sie davon ausgehen, dass Strings als Strings verglichen werden, und die passenden Funktionen einsetzen, wenn Sie einen Temporalwert mit einem String vergleichen möchten.

Das spezielle Datum `'0000-00-00'` kann als `'0000-00-00'` gespeichert und abgerufen werden. Wenn Sie ein `'0000-00-00'`-Datum in MyODBC benutzen, so wird es in MyODBC 2.50.12 und höher automatisch in `NULL` konvertiert, da ODBC mit Datumswerten dieser Art nicht umgehen kann.

Da MySQL die oben beschriebenen Konvertierungen vornimmt, funktionieren folgende Anweisungen:

    mysql> INSERT INTO tbl_name (idate) VALUES (19970505);
    mysql> INSERT INTO tbl_name (idate) VALUES ('19970505');
    mysql> INSERT INTO tbl_name (idate) VALUES ('97-05-05');
    mysql> INSERT INTO tbl_name (idate) VALUES ('1997.05.05');
    mysql> INSERT INTO tbl_name (idate) VALUES ('1997 05 05');
    mysql> INSERT INTO tbl_name (idate) VALUES ('0000-00-00');

    mysql> SELECT idate FROM tbl_name WHERE idate >= '1997-05-05';
    mysql> SELECT idate FROM tbl_name WHERE idate >= 19970505;
    mysql> SELECT MOD(idate,100) FROM tbl_name WHERE idate >= 19970505;
    mysql> SELECT idate FROM tbl_name WHERE idate >= '19970505';

Doch die folgende Anweisung funktioniert nicht:

    mysql> SELECT idate FROM tbl_name WHERE STRCMP(idate,'20030505')=0;

Da `STRCMP()` eine String-Funktion ist, konvertiert sie `idate` in einen String im Format `'YYYY-MM-DD'` und führt einen String-Vergleich durch. `'20030505'` wird nicht in das Datum `'2003-05-05'` konvertiert, um einen Datumsvergleich durchzuführen.

Wenn Sie den SQL-Modus `ALLOW_INVALID_DATES` eingestellt haben, gestattet MySQL Ihnen die Speicherung von Datumswerten bei nur rudimentärer Überprüfung: MySQL verlangt lediglich, dass der Tag im Bereich von 1 bis 31 und der Monat im Bereich von 1 bis 12 liegt.

Dadurch eignet sich MySQL gut für Webanwendungen, bei denen Jahr, Monat und Tag in drei verschiedenen Feldern abgerufen werden und in denen Sie genau das, was der Benutzer eingibt, speichern möchten (ohne das Datum zu validieren).

Wenn Sie nicht den SQL-Modus `NO_ZERO_IN_DATE` SQL verwenden, kann der Tag oder der Monat null sein. Das ist praktisch, wenn Sie in einer `DATE`-Spalte einen Geburtstag speichern möchten, dessen Datum Sie nur teilweise kennen.

Wenn Sie nicht den SQL-Modus `NO_ZERO_DATE` verwenden, gestattet Ihnen MySQL auch, `'0000-00-00'` als „Dummy-Datum“ zu speichern. Das ist manchmal praktischer als `NULL`-Werte.

Wenn sich das Datum nicht in einen vernünftigen Wert konvertieren lässt, wird eine `0` in der `DATE`-Spalte gespeichert und als `'0000-00-00'` abgerufen. Dies ist eine Frage von Schnelligkeit und Bequemlichkeit. Wir sind der Ansicht, dass der Datenbankserver dieselben Daten liefern sollte, die gespeichert wurden (selbst wenn diese Daten im Einzelfall nicht immer logisch richtig sind). Wir denken, dass es Sache der Anwendung ist, die Datumswerte zu überprüfen.

Wenn Sie wollen, dass MySQL die Daten überprüft und nur gültige zulässt (es sei denn, dies wird durch IGNORE außer Kraft gesetzt), müssen Sie den `sql_mode` auf `"NO_ZERO_IN_DATE,NO_ZERO_DATE"` einstellen.

### A.5.3. Probleme mit `NULL`-Werten

`NULL`-Werte stiften bei SQL-Neulingen immer wieder Verwirrung, da diese oft denken, `NULL` sei dasselbe wie der leere String `''`. Doch das ist nicht der Fall. Die folgenden Anweisungen sind beispielsweise völlig verschieden:

    mysql> INSERT INTO my_table (phone) VALUES (NULL);
    mysql> INSERT INTO my_table (phone) VALUES ('');

Beide Anweisungen fügen einen Wert in die `phone`-Spalte ein, die erste allerdings einen `NULL`-Wert und die zweite einen leeren String. Die erste Eingabe bedeutet so viel wie „Telefonnummer unbekannt“ und die zweite bedeutet „Die Person hat kein Telefon und somit keine Telefonnummer“.

Als Hilfe für den Umgang mit `NULL`-Werten sind die Operatoren `IS NULL` und `IS NOT NULL` sowie die Funktion `IFNULL()` da.

In SQL ergibt ein Vergleich zwischen `NULL` und irgendeinem anderen Wert nie einen Treffer, selbst wenn auch der andere Wert `NULL` ist. Ein Ausdruck, der `NULL` enthält, ergibt immer den Wert `NULL`, es sei denn, die Dokumentation der Operatoren und Funktionen, die an dem Ausdruck beteiligt sind, sagt ausdrücklich etwas anderes. Alle Spalten im folgenden Beispiel geben `NULL` zurück:

    mysql> SELECT NULL, 1+NULL, CONCAT('Invisible',NULL);

Wenn Sie Spaltenwerte suchen, die `NULL` sind, verwenden Sie bitte nicht den Test `expr = NULL`. Die folgende Anweisung gibt gar keine Zeilen zurück, da `expr = NULL` niemals wahr sein kann:

    mysql> SELECT * FROM my_table WHERE phone = NULL;

Wenn Sie `NULL`-Werte suchen, dann mit `IS NULL`. Die folgenden Anweisungen zeigen, wie man die Telefonnummer `NULL` und die leere Telefonnummer finden kann:

    mysql> SELECT * FROM my_table WHERE phone IS NULL;
    mysql> SELECT * FROM my_table WHERE phone = '';

Weitere Informationen und Beispiele finden Sie unter Abschnitt 3.3.4.6, „Mit `NULL`-Werten arbeiten“.

Sie können einer Spalte, die `NULL`-Werte enthält, einen Index hinzufügen, wenn Sie `MyISAM`, `InnoDB`, `BDB` oder `MEMORY` als Speicher-Engine einsetzen. Andernfalls müssen Sie die indizierte Spalte als `NOT NULL` deklarieren und können keine `NULL`-Werte in sie einfügen.

Wenn Sie Daten mit `LOAD DATA INFILE` lesen, werden leere oder fehlende Spalten mit `''` aktualisiert. Möchten Sie in eine Spalte einen `NULL`-Wert einfügen, so müssen Sie `\N` in die Datendatei schreiben. Das Literal „`NULL`“ kann unter bestimmten Umständen ebenfalls verwendet werden. Siehe Abschnitt 13.2.5, „`LOAD DATA INFILE`“.

`DISTINCT`, `GROUP BY` oder `ORDER BY` betrachten alle `NULL`-Werte als gleich.

`ORDER BY` stellt die `NULL`-Werte immer an den Anfang oder, wenn `DESC` für eine absteigende Sortierreihenfolge angegeben wurde, an das Ende.

Aggregatfunktionen (Summenfunktionen) wie `COUNT()`, `MIN()` und `SUM()` ignorieren `NULL`-Werte. Eine Ausnahme bildet die Funktion `COUNT(*)`, die Zeilen und nicht einzelne Spaltenwerte zählt. Die folgende Anweisung erstellt beispielsweise zwei Zählungen: eine Zählung der Zeilen in der Tabelle und eine Zählung der von `NULL` verschiedenen Werte in der Spalte `age`:

    mysql> SELECT COUNT(*), COUNT(age) FROM person;

Für manche Datentypen behandelt MySQL `NULL`-Werte ganz speziell. Wenn Sie `NULL` in eine `TIMESTAMP`-Spalte einfügen, werden Datum und Uhrzeit von jetzt eingefügt. Wenn Sie `NULL` in eine Integer-Spalte einfügen, die das `AUTO_INCREMENT`-Attribut hat, wird stattdessen die nächste Folgenummer eingesetzt.

### A.5.4. Probleme mit `alias`

Einen Alias können Sie verwenden, um eine Spalte in `GROUP BY`-, `ORDER BY`- oder `HAVING`-Klauseln zu benennen. Außerdem sind Aliasnamen nützlich, um Spalten bessere Namen zu verpassen:

    SELECT SQRT(a*b) AS root FROM tbl_name GROUP BY root HAVING root > 0;
    SELECT id, COUNT(*) AS cnt FROM tbl_name GROUP BY id HAVING cnt > 0;
    SELECT id AS 'Customer identity' FROM tbl_name;

Im Standard-SQL dürfen Sie in `WHERE`-Klauseln keine Spaltenaliase benutzen, da der Spaltenwert unter Umständen noch gar nicht festliegt, wenn der `WHERE`-Code ausgeführt wird. Die folgende Anfrage ist beispielsweise unzulässig:

    SELECT id, COUNT(*) AS cnt FROM tbl_name WHERE cnt > 0 GROUP BY id;

Die `WHERE`-Anweisung soll festlegen, welche Zeilen in den `GROUP BY`-Teil einfließen, während die `HAVING`-Klausel entscheiden soll, welche Zeilen der Ergebnismenge benutzt werden sollen.

### A.5.5. Rollback schlägt bei nichttransaktionssicheren Tabellen fehl

Wenn Sie die folgende Meldung beim Versuch eines `ROLLBACK` erhalten, so bedeutet dies, dass mindestens eine in der Transaktion verwendete Tabelle gar keine Transaktionen unterstützt:

    Änderungen an einigen nicht transaktionalen Tabellen konnten nicht zurückgerollt werden

Diese nichttransaktionssicheren Tabellen werden von der `ROLLBACK`-Anweisung gar nicht betroffen.

Wenn Sie nicht absichtlich transaktionssichere und nichttransaktionssichere Tabellen in der Transaktion mischen, tritt diese Fehlermeldung wahrscheinlich auf, weil eine Tabelle, die Sie für transaktionssicher gehalten haben, dies in Wirklichkeit nicht ist. Das kann passieren, wenn Sie eine Tabelle mit einer transaktionssicheren Speicher-Engine anlegen, die nicht von Ihrem mysqld-Server unterstützt wird (oder mit einer Startoption ausgeschaltet wurde). Wenn mysqld eine Speicher-Engine nicht unterstützt, wird eine `MyISAM`-Tabelle angelegt, und diese ist nicht transaktionssicher.

Welche Speicher Engine eine Tabelle verwendet, erfahren Sie mit folgenden Anweisungen:

    SHOW TABLE STATUS LIKE 'tbl_name';
    SHOW CREATE TABLE tbl_name;

Siehe Abschnitt 13.5.4.21, „`SHOW TABLE STATUS`“, und Abschnitt 13.5.4.6, „`SHOW CREATE TABLE`“.

Welche Speicher-Engines Ihr mysqld-Server verwendet, finden Sie mit dieser Anweisung heraus:

    SHOW ENGINES;

Sie können jedoch auch nachfolgende Anweisung ausführen und den Wert der Variablen betrachten, die für die von Ihnen gewünschte Speicher-Engine steht:

    SHOW VARIABLES LIKE 'have_%';

Um beispielsweise festzustellen, ob die Speicher-Engine `InnoDB` zur Verfügung steht, schauen Sie auf den Wert der Variablen `have_innodb`.

Siehe Abschnitt 13.5.4.9, „`SHOW ENGINES`“, und Abschnitt 13.5.4.24, „`SHOW VARIABLES`“.

### A.5.6. Zeilen aus verwandten Tabellen löschen

Wenn die `DELETE`-Anweisung für `related_table` insgesamt mehr als 1 Mbyte beträgt (der Standardwert der Systemvariablen `max_allowed_packet`), dann müssen Sie sie aufteilen und als mehrere kleinere `DELETE`-Anweisungen ausführen. Am schnellsten läuft ein `DELETE`, wenn Sie nur 100 bis 1.000 `related_column`-Werte pro (indizierter) Anweisung angeben. Wenn `related_column` keinen Index hat, ist die Geschwindigkeit von der Anzahl der Argumente der `IN`-Klausel unabhängig.

### A.5.7. Lösung von Problemen mit nicht übereinstimmenden Zeilen

Wenn Sie eine komplizierte Anfrage ausführen, die viele Tabellen benutzt, aber nichts zurückgibt, können Sie mit folgendem Verfahren herausfinden, was schief gegangen ist:

1. Testen Sie die Anfrage mit `EXPLAIN`, um offensichtliche Fehler zu finden. Siehe Abschnitt 7.2.1, „`EXPLAIN`-Syntax (Informationen über ein `SELECT` erhalten)“.

2. Wählen Sie nur diejenigen Spalten aus, die in der `WHERE`-Klausel aufgeführt sind.

3. Entfernen Sie immer nur eine einzige Tabelle aus der Anfrage so lange, bis sie irgendwelche Zeilen zurückgibt. Wenn die Tabellen groß sind, sollten Sie in Ihrer Anfrage `LIMIT 10` verwenden.

4. Geben Sie eine `SELECT`-Anweisung für die Spalte der zuletzt aus der Anfrage entfernten Tabelle, die eigentlich eine passende Zeile hätte enthalten müssen.

5. Wenn Sie `FLOAT`- oder `DOUBLE`-Spalten mit Dezimalzahlen vergleichen, können Sie keine Gleichheitsvergleiche (`=`) durchführen. Dieses Problem tritt in allen Programmiersprachen auf, da nicht alle Fließkommawerte mit einer exakten Genauigkeit gespeichert werden können. In manchen Fällen können Sie dies beheben, indem Sie aus einem `FLOAT`- einen `DOUBLE`-Wert machen. Siehe Abschnitt A.5.8, „Probleme mit Fließkommavergleichen“.

6. Wenn Sie den Fehler immer noch nicht finden können, legen Sie einen minimalen Testfall an, der mit `mysql test < query.sql` ausgeführt werden kann und Ihre Probleme verdeutlicht. Eine Testdatei legen Sie an, indem Sie die Tabellen mit mysqldump --quick db_name `tbl_name_1` ... `tbl_name_n` > query.sql kopieren. Öffnen Sie die Datei in einem Editor, entfernen Sie einige eingefügte Zeilen (wenn mehr da sind, als zur Verdeutlichung des Problems notwendig ist) und fügen Sie am Ende der Datei Ihre `SELECT`-Anweisung an.

   Mit folgenden Befehlen können Sie sich vergewissern, dass Ihre Testdatei das Problem zeigt:

       shell> mysqladmin create test2
       shell> mysql test2 < query.sql

   Hängen Sie die Testdatei an einen Bugreport an. Diesen können Sie uns senden, wie in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“, beschrieben.

### A.5.8. Probleme mit Fließkommavergleichen

Der folgende Abschnitt ist vor allem für `DOUBLE`- und `FLOAT`-Spalten interessant, da Fließkommazahlen von Natur aus ungenau sind. MySQL führt `DECIMAL`-Operationen mit einer Genauigkeit von 64 Dezimalstellen aus. Das müsste die meisten Probleme im Hinblick auf die Genauigkeit von `DECIMAL`-Spalten lösen.

Fließkommazahlen stiften gelegentlich Verwirrung, da sie in einer Computerarchitektur nicht als exakte Werte gespeichert werden. Das, was der Bildschirm zeigt, ist in der Regel nicht der genaue Wert der Zahl. Die Datentypen `FLOAT` und `DOUBLE` sind Fließkommatypen. `DECIMAL`-Spalten speichern Werte mit einer exakten Anzahl Stellen, weil sie als Strings dargestellt werden.

Das folgende Beispiel verdeutlicht das Problem an einem `DOUBLE`:

    mysql> CREATE TABLE t1 (i INT, d1 DOUBLE, d2 DOUBLE);
    mysql> INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
        -> (2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
        -> (2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
        -> (4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
        -> (5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
        -> (6, 0.00, 0.00), (6, -51.40, 0.00);

    mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b
        -> FROM t1 GROUP BY i HAVING a <> b;

    +------+-------+------+
    | i    | a     | b    |
    +------+-------+------+
    |    1 |  21.4 | 21.4 |
    |    2 |  76.8 | 76.8 |
    |    3 |   7.4 |  7.4 |
    |    4 |  15.4 | 15.4 |
    |    5 |   7.2 |  7.2 |
    |    6 | -51.4 |    0 |
    +------+-------+------+

Das Ergebnis ist richtig. Auch wenn die ersten fünf Datensätze nicht so aussehen, als würden sie den Test bestehen (die Werte von `a` und `b` sehen nicht verschieden aus), können sie dennoch unterschiedlich sein, da sie womöglich in der zehnten Nachkommastelle oder so (je nach Computerarchitektur) eine Abweichung aufweisen.

Wären die Spalten `d1` und `d2` als `DECIMAL` statt als `DOUBLE` definiert, so hätte die `SELECT`-Anfrage nur eine einzige Zeile geliefert, nämlich die letzte der obigen Tabelle.

## A.6. Probleme im Zusammenhang mit dem Optimierer

MySQL ermittelt den besten Ausführungsweg für eine Anfrage mit einem kostenorientierten Optimierer. In vielen Fällen kann MySQL den bestmöglichen Ausführungsplan berechnen, aber manchmal hat es nicht genügend Informationen über die Daten und muss „fundierte“ Annahmen über die Daten treffen.

Wenn MySQL einmal nicht das Richtige tun sollte, stehen folgende Tools als Hilfestellung zur Verfügung:

- Die `EXPLAIN`-Anweisung lässt erkennen, wie MySQL eine Anfrage verarbeitet. Um sie zu benutzen, setzen Sie einfach das Schlüsselwort `EXPLAIN` vor Ihre `SELECT`-Anweisung:

      mysql> EXPLAIN SELECT * FROM t1, t2 WHERE t1.i = t2.i;

  `EXPLAIN` wird in Abschnitt 7.2.1, „`EXPLAIN`-Syntax (Informationen über ein `SELECT` erhalten)“, genauer beschrieben.

- Mit `ANALYZE TABLE `tbl_name`` können Sie die Schlüsselverteilungen für die gescannte Tabelle aktualisieren. Siehe auch Abschnitt 13.5.2.1, „`ANALYZE TABLE`“.

- Wenn Sie für die gescannte Tabelle die `FORCE INDEX`-Anweisung geben, teilen Sie MySQL dadurch mit, dass Tabellenscans im Vergleich zur Verwendung des vorgegebenen Indexes sehr aufwändig sind. Siehe Abschnitt 13.2.7, „`SELECT`“.

      SELECT * FROM t1, t2 FORCE INDEX (index_for_column)
      WHERE t1.col_name=t2.col_name;

  `USE INDEX` und `IGNORE INDEX` können ebenfalls nützlich sein.

- Globale und tabellenspezifische `STRAIGHT_JOIN`s. Siehe Abschnitt 13.2.7, „`SELECT`“.

- Sie können auch globale oder Thread-spezifische Systemvariablen einstellen, zum Beispiel indem Sie mysqld mit der Option `--max-seeks-for-key=1000` starten oder dem Optimierer mit `SET max_seeks_for_key=1000` sagen, dass er davon ausgehen soll, dass kein Schlüsselscan mehr als 1.000 Schlüsselsuchoperationen bedeutet. Siehe Abschnitt 5.2.2, „Server-Systemvariablen“.

## A.7. Tabellendefinitionsbezogene Themen

### A.7.1. Probleme mit `ALTER TABLE`

`ALTER TABLE` stellt die Tabelle auf den aktuellen Zeichensatz um. Wenn Sie während der Ausführung von `ALTER TABLE` einen Fehler wegen doppelt vorhandener Schlüssel bekommen, liegt dies entweder daran, dass der neue Zeichensatz zwei Schlüssel demselben Wert zuordnet, oder daran, dass die Tabelle beschädigt ist. Im zweiten Fall müssen Sie eine `REPAIR TABLE`-Anweisung auf der Tabelle ausführen.

Wenn `ALTER TABLE` mit der folgenden Fehlermeldung abbricht, kann dies daran liegen, dass MySQL bei einer vorherigen `ALTER TABLE`-Operation abgestürzt ist und noch eine alte Tabelle namens `A-`xxx`` oder `B-`xxx`` in der Gegend herumfliegt:

    Error on rename of './database/name.frm'
    to './database/B-xxx.frm' (Errcode: 17)

In diesem Fall gehen Sie in das Data Directory von MySQL und löschen alle Dateien, deren Namen mit `A-` oder `B-` anfangen. (Oder Sie verschieben sie an einen anderen Ort, anstatt sie zu löschen).

`ALTER TABLE` funktioniert folgendermaßen:

- Erzeuge eine neue Tabelle namens `A-`xxx`` mit den gewünschten Strukturänderungen.

- Kopiere alle Zeilen der Originaltabelle in `A-`xxx``.

- Benenne die Originaltabelle in `B-`xxx`` um.

- Gib `A-`xxx`` den ursprünglichen Namen der Tabelle.

- Lösche `B-`xxx``.

Wenn bei der Umbenennungsoperation etwas schief geht, versucht MySQL, die Änderungen rückgängig zu machen. Bei ernsthaften Problemen (die eigentlich nicht vorkommen sollten) könnte MySQL die alte Tabelle als `B-`xxx`` zurücklassen. Mit einer einfachen Umbenennung der Tabellendateien auf Systemebene müssten Sie Ihre Daten zurückbekommen.

Wenn Sie `ALTER TABLE` auf einer transaktionssicheren Tabelle ausführen oder Windows oder OS/2 benutzen, wird `ALTER TABLE` eine Sperre der Tabelle aufheben, falls Sie zuvor eine `LOCK TABLE`-Anweisung auf ihr ausgeführt haben, da `InnoDB` und diese Betriebssysteme keine Tabelle löschen können, die gerade in Gebrauch ist.

### A.7.2. Wie man die Reihenfolge der Spalten in einer Tabelle ändert

Zuerst müssen Sie überlegen, ob es wirklich notwendig ist, die Spaltenreihenfolge in der Tabelle zu ändern. Das Hauptanliegen von SQL ist ja schließlich, die Anwendung vom Format der Datenspeicherung abzukoppeln. Sie sollten immer die Reihenfolge angeben, in der Sie Ihre Daten abholen möchten. Die erste der folgenden Anweisungen gibt die Spalten in der Reihenfolge `col_name1`, `col_name2`, `col_name3` zurück, und die zweite in der Reihenfolge `col_name1`, `col_name3`, `col_name2`:

    mysql> SELECT col_name1, col_name2, col_name3 FROM tbl_name;
    mysql> SELECT col_name1, col_name3, col_name2 FROM tbl_name;

Wenn Sie dennoch die Reihenfolge der Spalten ändern möchten, tun Sie das folgendermaßen:

1. Sie erzeugen eine neue Tabelle, in der die Spalten die neue Reihenfolge haben.

2. Sie führen folgende Anweisung aus:

       mysql> INSERT INTO new_table
           -> SELECT columns-in-new-order FROM old_table;

3. Sie löschen die `old_table` oder benennen sie um.

4. Sie geben der neuen Tabelle den Namen des Originals:

       mysql> ALTER TABLE new_table RENAME old_table;

`SELECT *` eignet sich gut für Testanfragen. In einer Anwendung sollten Sie sich jedoch nie darauf verlassen, mit `SELECT *` die Spalten nach ihrer Position abzufragen. Die Reihenfolge und Position, in der die Spalten zurückgegeben werden, kann sich ändern, wenn Sie Spalten neu einfügen, verschieben oder löschen. Eine einfache Änderung an der Tabellenstruktur kann so Ihre Anwendung bereits zum Absturz bringen.

### A.7.3. Probleme mit TEMPORARY TABLE

Für die Nutzung von `TEMPORARY`-Tabellen gibt es folgende Beschränkungen:

- Eine `TEMPORARY`-Tabelle kann nur den Typ `HEAP`, `ISAM`, `MyISAM`, `MERGE` oder `InnoDB` haben.

- Eine `TEMPORARY`-Tabelle kann nicht mehrmals in derselben Anfrage benutzt werden. Das Folgende funktioniert beispielsweise nicht:

      mysql> SELECT * FROM temp_table, temp_table AS t2;
      ERROR 1137: Can't reopen table: 'temp_table'

- Die `SHOW TABLES`-Anweisung führt keine `TEMPORARY`-Tabellen auf.

- Sie können eine `TEMPORARY`-Tabelle nicht mit `RENAME`, sondern nur mit `ALTER TABLE` umbenennen:

      mysql> ALTER TABLE orig_name RENAME new_name;

- Im Zusammenhang mit Replikation können temporäre Tabellen Probleme machen. Weiteres erfahren Sie unter Abschnitt 6.8, „Replikation: Features und bekannte Probleme“.

## A.8. Bekannte Fehler und konzeptionelle Unzulänglichkeiten in MySQL

Die folgenden Fehler sind in den neueren Versionen von MySQL bekannt geworden.

Informationen über plattformspezifische Probleme finden Sie in den Anleitungen zur Installation und Portierung von MySQL unter Abschnitt 2.12, „Betriebssystemspezifische Anmerkungen“, und Anhang E, Anmerkungen zur Portierung auf andere Systeme.

### A.8.1. Offene Probleme in MySQL

Die folgenden Probleme sind bekannt und werden vorrangig gelöst:

- Wenn Sie einen `NULL`-Wert mit einer Unterabfrage kombinieren, die eine `ALL/ANY/SOME`-Klausel hat, und die Unterabfrage ein leeres Ergebnis zurückliefert, kann der Vergleich das nicht standardmäßige Resultat `NULL` ergeben anstatt `TRUE` oder `FALSE`. Dies wird in MySQL 5.1 behoben.

- Die Optimierung von Unterabfragen ist bei `IN` weniger effizient als bei `=`.

- Selbst wenn Sie `lower_case_table_names=2` verwenden (damit sich MySQL an die Groß-/Kleinschreibung von Datenbank- und Tabellennamen erinnert) kann MySQL sich diese nicht für Datenbanknamen im Zusammenhang mit der Funktion `DATABASE()` oder den diversen Logs merken (dies gilt für Systeme, die nicht zwischen Groß- und Kleinschreibung unterscheiden).

- Das Löschen eines `FOREIGN KEY`-Constraints funktioniert nicht in einer Replikation, da der Constraint auf dem Slave unter Umständen einen anderen Namen hat.

- `REPLACE` (und `LOAD DATA` mit der `REPLACE`-Option) löst kein `ON DELETE CASCADE` aus.

- `DISTINCT` mit `ORDER BY` funktioniert nicht in `GROUP_CONCAT()`, wenn Sie nicht nur die Spalten verwenden, die in der `DISTINCT`-Liste aufgeführt sind.

- Wenn ein Benutzer eine langwierige Transaktion laufen lässt und ein anderer Benutzer eine Tabelle löscht, die von der Transaktion geändert wird, besteht ein gewisses Risiko, dass der `DROP TABLE` im Binärlog festgehalten wird, bevor die Tabelle in der Transaktion benutzt wird. Dies wollen wir beheben, indem wir den `DROP TABLE`-Befehl so lange aussetzen lassen, bis die Tabelle in keiner Transaktion mehr benutzt wird.

- Wenn Sie einen großen Integer-Wert (zwischen 263 und 264–1) in eine Decimal- oder String-Spalte einfügen, wird er als negativer Wert geschrieben, da die Zahl als vorzeichenbehafteter Integer ausgewertet wird.

- `FLUSH TABLES WITH READ LOCK` kann `COMMIT` nicht blockieren, wenn der Server ohne Binärlogging läuft. Das kann zu Konsistenzproblemen mit Tabellen führen, wenn Sie eine vollständige Datensicherung ausführen.

- `ANALYZE TABLE` kann `BDB`-Tabellen unter Umständen bis zum nächsten Neustart von mysqld unbenutzbar machen. Wenn dies geschieht, suchen Sie in der Fehlerdatei von MySQL nach Fehlern der folgenden Art:

      001207 22:07:56  bdb:  log_flush: LSN past current end-of-log

- Führen Sie kein `ALTER TABLE` auf einer `BDB`-Tabelle aus, auf der Transaktionen mit mehreren Anweisungen laufen. Dies können Sie erst nach Abschluss aller dieser Transaktionen tun, da die Transaktion ansonsten eventuell ignoriert wird.

- `ANALYZE TABLE`, `OPTIMIZE TABLE` und `REPAIR TABLE` können Probleme mit Tabellen verursachen, die mit `INSERT DELAYED` laufen.

- Auch mit `LOCK TABLE ...` und `FLUSH TABLES ...` ist nicht gewährleistet, dass nicht noch eine halbfertige Transaktion auf der Tabelle abläuft.

- `BDB`-Tabellen öffnen sich relativ langsam. Wenn Sie viele `BDB`-Tabellen in einer Datenbank haben, braucht der mysql-Client viel Zeit, es sei denn, Sie verwenden die Option `-A` oder `rehash`. Das macht sich besonders bei großen Tabellen-Caches bemerkbar.

- Replikation verwendet Logging auf Anweisungsebene: Der Master schreibt die ausgeführten Anweisungen in das Binärlog. Dies ist eine sehr schnelle, kompakte und wirkungsvolle Loggingmethode, die in den meisten Fällen auch perfekt funktioniert.

  Es ist jedoch möglich, dass Unterschiede zwischen den Daten von Master und Slave auftreten, wenn eine Anfrage so entworfen wurde, dass sie Daten in nichtdeterministischer Weise ändert (was allerdings generell, auch außerhalb einer Replikation, nicht zu empfehlen ist).

  Beispielsweise:

  - `CREATE ... SELECT`- oder `INSERT ... SELECT`-Anweisungen, die null oder `NULL`-Werte in eine `AUTO_INCREMENT`-Spalte einfügen.

  - `DELETE`, wenn Sie Zeilen aus einer Tabelle löschen, die Fremdschlüssel mit `ON DELETE CASCADE`-Eigenschaften hat.

  - `REPLACE ... SELECT`, `INSERT IGNORE ... SELECT`, wenn Sie in den eingefügten Daten Schlüsselduplikate haben.

  Genau dann, wenn die vorangegangenen Anfragen keine `ORDER BY`-Klausel haben, die eine deterministische Sortierreihenfolge garantiert.

  So kann beispielsweise ein `SELECT` für `INSERT ... SELECT` ohne `ORDER BY`-Klausel Zeilen in einer anderen Reihenfolge zurückliefern (was dazu führt, dass eine Zeile einen unterschiedlichen Rang und somit auch unterschiedliche Nummern in der `AUTO_INCREMENT`-Spalte haben kann), je nachdem, wie sich die Optimierer von Master und Slave entscheiden.

  Eine Anfrage wird auf Master und Slave nur in folgenden Fällen unterschiedlich optimiert:

  - Wenn die Tabelle auf dem Master mit einer anderen Speicher-Engine als auf dem Slave gespeichert wird. (Es ist nämlich möglich, auf Master und Slave verschiedene Speicher-Engines zu verwenden. So können Sie beispielsweise `InnoDB` auf dem Master und `MyISAM` auf dem Slave einsetzen, wenn der Slave weniger Festplattenspeicher zur Verfügung hat.)

  - Wenn die Größen der MySQL-Puffer (`key_buffer_size` und so weiter) auf Master und Slave unterschiedlich sind.

  - Wenn Master und Slave mit unterschiedlichen MySQL-Versionen laufen und der Optimierungscode einen Unterschied zwischen diesen beiden Versionen macht.

  Dieses Problem kann auch die Datenbankwiederherstellung mit mysqlbinlog|mysql beeinträchtigen.

  Am einfachsten lässt sich dieses Problem verhindern, wenn Sie den oben erwähnten nichtdeterministischen Anfragen eine `ORDER BY`-Klausel hinzufügen, um zu gewährleisten, dass die Zeilen immer in derselben Reihenfolge gespeichert oder modifiziert werden.

  In künftigen MySQL-Versionen werden wir automatisch eine `ORDER BY`-Klausel hinzufügen, wo sie nötig ist.

Die folgenden Probleme sind bekannt und werden bald behoben:

- Die Logdateinamen basieren auf dem Namen des Serverhosts (sofern Sie nicht mit der Startoption einen Dateinamen vorgeben). Wenn Sie Ihren Hostnamen ändern möchten, müssen Sie Optionen wie beispielsweise `--log-bin=`old_host_name`-bin` verwenden. Oder Sie benennen die alten Dateien mit dem neuen Hostnamen um (wenn es Binärlogs sind, müssen Sie dazu auch die Indexdatei des Binärlogs bearbeiten und die Binlognamen ebenfalls ändern). Siehe Abschnitt 5.2.1, „Befehlsoptionen für mysqld“.

- mysqlbinlog löscht keine temporären Dateien, die nach einem `LOAD DATA INFILE`-Befehl übrig bleiben. Siehe Abschnitt 8.8, „mysqlbinlog — Hilfsprogramm für die Verarbeitung binärer Logdateien“.

- `RENAME` funktioniert nicht mit `TEMPORARY`-Tabellen oder Tabellen, die in einer `MERGE`-Tabelle benutzt werden.

- Aufgrund der Art und Weise, wie Tabellenformatdateien (`.frm`-Dateien) gespeichert werden, können Sie Zeichen 255 (`CHAR(255)`) nicht in Tabellennamen, Spaltennamen und Enumerationen verwenden. Dies soll in Version 5.1 behoben werden, wenn wir neue Formatdateien für die Tabellendefinitionen implementieren.

- Wenn Sie `SET CHARACTER SET` benutzen, können Sie keine übersetzten Zeichen in den Namen von Datenbanken, Tabellen und Spalten verwenden.

- Sie dürfen kein ‘`_`’ oder ‘`%`’ mit `ESCAPE` in `LIKE ... ESCAPE` verwenden.

- Wenn Sie in einer `DECIMAL`-Spalte dieselbe Zahl in verschiedenen Formaten gespeichert haben (beispielsweise `+01.00`, `1.00`, `01.00`), kann es passieren, dass `GROUP BY` diese Werte als unterschiedlich betrachtet.

- Sie können den Server nicht in einem anderen Verzeichnis bauen, wenn Sie MIT-pthreads verwenden. Da sich dies nur durch eine Änderung von MIT-pthreads beheben ließe, werden wir es wahrscheinlich nicht reparieren können. Siehe auch Abschnitt 2.8.5, „Anmerkungen zu MIT-pthreads“.

- `BLOB`- und `TEXT`-Werte können in `GROUP BY`, `ORDER BY` oder `DISTINCT` nicht zuverlässig benutzt werden, da in diesen Fällen zum Vergleich von `BLOB`-Werten nur die ersten `max_sort_length` Bytes herangezogen werden. Der Standardwert von `max_sort_length` beträgt 1.024 und kann beim Serverstart oder zur Laufzeit geändert werden.

- Numerische Berechnungen werden mit `BIGINT` oder `DOUBLE` ausgeführt (beide sind normalerweise 64 Bits lang). Welche Genauigkeit sie haben, hängt von der Funktion ab. Im Allgemeinen werden Bitfunktionen mit einer `BIGINT`-Genauigkeit, `IF` und `ELT()` mit einer `BIGINT`- oder `DOUBLE`-Genauigkeit und alles Übrige mit einer `DOUBLE`-Genauigkeit ausgeführt. Sie sollten möglichst (außer für Bitfelder) keine sehr langen Werte verwenden, wenn diese länger als 63 Bits (9223372036854775807) werden können.

- In einer Tabelle dürfen bis zu 255 `ENUM`- und `SET`-Spalten vorhanden sein.

- In `MIN()`, `MAX()` und anderen Aggregatfunktionen vergleicht MySQL `ENUM`- und `SET`-Spalten gegenwärtig nach ihrem Stringwert anstatt nach der relativen Position des Strings in der Menge.

- mysqld_safe leitet alle Meldungen von mysqld in das mysqld-Log. Wenn Sie das Log mit mysqladmin refresh schließen und neu öffnen, besteht jedoch das Problem, dass `stdout` und `stderr` weiterhin in das alte Log umgeleitet werden. Wenn Sie viel mit `--log` arbeiten, sollten Sie mysqld_safe so bearbeiten, dass es Logeinträge in ``host_name`.err` statt in ``host_name`.log` schreibt, damit Sie den Speicherplatz des alten Logs leichter zurückholen können, indem Sie es einfach löschen und mysqladmin refresh ausführen.

- In einer `UPDATE`-Anweisung werden die Spalten von links nach rechts aktualisiert. Wenn Sie eine aktualisierte Spalte benutzen, bekommen Sie den aktualisierten statt des ursprünglichen Werts. Die folgende Anweisung inkrementiert beispielsweise `KEY` um `2` und nicht um `1`:

      mysql> UPDATE tbl_name SET KEY=KEY+1,KEY=KEY+1;

- Sie können zwar in derselben Anfrage mehrere temporäre Tabellen benutzen, aber nicht dieselbe zweimal. Das Folgende funktioniert beispielsweise nicht:

      mysql> SELECT * FROM temp_table, temp_table AS t2;
      ERROR 1137: Can't reopen table: 'temp_table'

- Der Optimierer behandelt `DISTINCT` unterschiedlich, je nachdem, ob Sie in einem Join „verborgene“ Spalten benutzen oder nicht. Verborgene Spalten werden in einem Join als Teil des Ergebnisses betrachtet (obwohl sie nicht angezeigt werden), während sie in normalen Anfragen nicht an einem `DISTINCT`-Vergleich teilnehmen. Dies werden wir wahrscheinlich in Zukunft dahingehend ändern, dass die verborgenen Spalten bei `DISTINCT` nicht mehr am Vergleich beteiligt werden.

  Ein Beispiel dafür ist:

      SELECT DISTINCT mp3id FROM band_downloads
             WHERE userid = 9 ORDER BY id DESC;

  und

      SELECT DISTINCT band_downloads.mp3id
             FROM band_downloads,band_mp3
             WHERE band_downloads.userid = 9
             AND band_mp3.id = band_downloads.mp3id
             ORDER BY band_downloads.id DESC;

  Im zweiten Fall bekommen Sie mit MySQL Server 3.23.x vielleicht zwei identische Zeilen in der Ergebnismenge (da die Werte in der verborgenen `id`-Spalte unterschiedlich sein können).

  Beachten Sie, dass dies nur in Anfragen ohne `ORDER BY`-Spalten im Ergebnis passieren kann.

- Wenn Sie eine `PROCEDURE` auf einer Anfrage ausführen, die eine leere Menge zurückgibt, wird die `PROCEDURE` in manchen Fällen die Spalten nicht transformieren.

- Beim Anlegen einer Tabelle vom Typ `MERGE` wird nicht geprüft, ob die Typen der zugrunde liegenden Tabellen kompatibel sind.

- Wenn Sie einer Tabelle, die in einer `MERGE`-Tabelle benutzt wird, mit `ALTER TABLE` einen `UNIQUE`-Index hinzufügen und dann einen normalen Index auf die `MERGE`-Tabelle legen, ist die Reihenfolge der Schlüssel bei Tabellen anders, wenn zuvor ein Nicht-`UNIQUE`-Schlüssel in der Tabelle bestand. Der Grund: `ALTER TABLE` setzt `UNIQUE`-Indizes vor normale Indizes, um so früh wie möglich Schlüsselduplikate erkennen zu können.

Dies ist eine Übersetzung des MySQL-Referenzhandbuchs, das sich auf dev.mysql.com befindet. Das ursprüngliche Referenzhandbuch ist auf Englisch, und diese Übersetzung ist nicht notwendigerweise so aktuell wie die englische Ausgabe. Das vorliegende deutschsprachige Handbuch behandelt MySQL bis zur Version 5.1.

Zurück |  | Weiter
Kapitel 26. MySQL erweitern | Zum Anfang | Anhang B. Fehlercodes und -meldungen