Anhang A. Probleme und häufig auftretende Fehler

Inhaltsverzeichnis

A.1. Wie man feststellt, was Probleme verursacht
A.2. Einige häufige Fehler bei der Benutzung von MySQL
A.2.1. Access denied-Fehler
A.2.2. Can't connect to [local] MySQL server-Fehler
A.2.3. Client does not support authentication protocol
A.2.4. Interaktive Kennworteingabe schlägt fehl
A.2.5. Host '...' is blocked-Fehler
A.2.6. Too many connections-Fehler
A.2.7. No free memory-Fehler
A.2.8. MySQL server has gone away-Fehler
A.2.9. Packet too large-Fehler
A.2.10. Kommunikationsfehler/abgebrochene Verbindung
A.2.11. The table is full-Fehler
A.2.12. Can't create/write to file-Fehler
A.2.13. Command out of sync-Fehler in Client
A.2.14. User ignored-Fehler
A.2.15. Table 'xxx' doesn't exist-Fehler
A.2.16. Can't initialize charset xxx-Fehler
A.2.17. Datei nicht gefunden
A.3. Installationsbezogene Themen
A.3.1. Probleme beim Linken mit der MySQL-Clientbibliothek
A.3.2. Probleme mit Dateirechten
A.4. Administrationsbezogene Themen
A.4.1. Wie ein vergessenes Kennwort zurückgesetzt wird
A.4.2. Was zu tun ist, wenn MySQL andauernd abstürzt
A.4.3. Wie MySQL mit vollen Festplatten umgeht
A.4.4. Wohin MySQL temporäre Dateien speichert
A.4.5. Wie Sie die MySQL-Socketdatei /tmp/mysql.sock schützen oder ändern
A.4.6. Probleme mit Zeitzonen
A.5. Anfragenbezogene Themen
A.5.1. Groß-/Kleinschreibung beim Suchen
A.5.2. Probleme bei der Benutzung von DATE-Spalten
A.5.3. Probleme mit NULL-Werten
A.5.4. Probleme mit alias
A.5.5. Rollback schlägt bei nichttransaktionssicheren Tabellen fehl
A.5.6. Zeilen aus verwandten Tabellen löschen
A.5.7. Lösung von Problemen mit nicht übereinstimmenden Zeilen
A.5.8. Probleme mit Fließkommavergleichen
A.6. Probleme im Zusammenhang mit dem Optimierer
A.7. Tabellendefinitionsbezogene Themen
A.7.1. Probleme mit ALTER TABLE
A.7.2. Wie man die Reihenfolge der Spalten in einer Tabelle ändert
A.7.3. Probleme mit TEMPORARY TABLE
A.8. Bekannte Fehler und konzeptionelle Unzulänglichkeiten in MySQL
A.8.1. Offene Probleme in MySQL

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:

FehlercodeBeschreibung
CR_SERVER_GONE_ERRORDer Client konnte keine Frage an den Server senden.
CR_SERVER_LOSTDer 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:

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_JOINs. 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.