Inhaltsverzeichnis
Access denied
-FehlerCan't connect to [local] MySQL server
-FehlerClient does not support authentication protocol
Host '...' is blocked
-FehlerToo many connections
-FehlerNo free memory
-FehlerMySQL server has gone away
-FehlerPacket too large
-FehlerThe table is full
-FehlerCan't create/write to file
-FehlerCommand out of sync
-Fehler in ClientUser ignored
-FehlerTable 'xxx' doesn't exist
-FehlerCan't initialize charset xxx
-Fehler/tmp/mysql.sock
schützen oder ändernDATE
-SpaltenNULL
-Wertenalias
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.
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.
Access denied
-FehlerCan't connect to [local] MySQL server
-FehlerClient does not support authentication protocol
Host '...' is blocked
-FehlerToo many connections
-FehlerNo free memory
-FehlerMySQL server has gone away
-FehlerPacket too large
-FehlerThe table is full
-FehlerCan't create/write to file
-FehlerCommand out of sync
-Fehler in ClientUser ignored
-FehlerTable 'xxx' doesn't exist
-FehlerCan't initialize charset xxx
-FehlerIn 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.
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“.
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.
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/.
Starten Sie den Registrierungs-Editor
(Regedt32.exe
).
Suchen Sie folgenden Registrierungsschlüssel:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
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).
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).
Schließen Sie den Registrierungs-Editor.
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.
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 = '
mysql>some_host
' AND User = 'some_user
';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:
Starten Sie mysqld mit der Option
--old-passwords
.
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“.
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.
Wenn folgender Fehler gemeldet wird, bedeutet dies, dass
mysqld vom Host
'
viele
Verbindungsanforderungen empfangen hat, die in der Mitte
unterbrochen wurden:
host_name
'
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.
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.
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.
In diesem Abschnitt wird auch der hiermit verwandte
Lost connection to server during query
-Fehler
behandelt.
Die häufigste Ursache eines MySQL server has gone
away
-Fehlers ist, dass der Server die Verbindung wegen
eines Timeouts geschlossen hat. In diesem Fall wird
normalerweise einer der folgenden Fehlercodes (je nach
Betriebssystem) gemeldet:
Fehlercode | Beschreibung |
CR_SERVER_GONE_ERROR | Der Client konnte keine Frage an den Server senden. |
CR_SERVER_LOST | Der Client konnte zwar ohne Fehler auf den Server schreiben, erhielt aber keine (oder keine vollständige) Antwort auf die Frage. |
Nach Voreinstellung schließt der Server die Verbindung, wenn
nichts geschieht, nach acht Stunden. Dieses Zeitlimit können
Sie in der Variablen wait_timeout
ändern,
wenn Sie mysqld starten. Siehe
Abschnitt 5.2.2, „Server-Systemvariablen“.
Wenn Sie ein Skript verwenden, müssen Sie die Anfrage nur
erneut absetzen, damit der Client sich automatisch erneut
verbindet. Das setzt voraus, dass die automatische Neuverbindung
im Client eingeschaltet ist (was beim
mysql
-Kommandozeilen-Client standardmäßig
der Fall ist).
Oft kommen MySQL server has gone away
-Fehler
auch aus folgenden Gründen zustande:
Sie (oder der Datenbankadministrator) haben den laufenden
Thread mit einer KILL
-Anweisung oder
einem mysqladmin kill-Befehl angehalten.
Sie haben versucht, eine Anfrage nach dem Schließen der Serververbindung abzusetzen. Dies weist auf einen Fehler in der Anwendungslogik hin, der korrigiert werden muss.
Sie haben einen Timeout von der TCP/IP-Verbindung auf der
Clientseite erhalten. Dazu kann es bei folgenden Befehlen
kommen: mysql_options(..., MYSQL_OPT_READ_TIMEOUT,
...)
oder mysql_options(...,
MYSQL_OPT_WRITE_TIMEOUT, ...)
. In diesem Fall
können Sie Ihr Problem lösen, indem Sie den Timeout
heraufsetzen.
Sie haben einen Timeout auf der Serverseite und die
automatische Neuverbindung ist im Client deaktiviert worden
(das Flag reconnect
in der
MYSQL
-Struktur ist gleich 0).
Sie verwenden einen Windows-Client und der Server hat die
Verbindung beendet (wahrscheinlich, weil
wait_timeout
abgelaufen ist), bevor der
Befehl gegeben wurde.
Das Problem mit Windows besteht darin, dass MySQL manchmal keinen Fehler vom Betriebssystem gemeldet bekommt, wenn es Daten in die TCP/IP-Verbindung mit dem Server schreibt. Stattdessen wird der Fehler erst bei dem Versuch gemeldet, Daten aus dieser Verbindung zu lesen.
Selbst wenn das Flag reconnect
in der
MYSQL
-Struktur gleich 1 ist, wird sich
MySQL in diesem Fall nicht automatisch neu verbinden und die
Anfrage neu absetzen, da es nicht wissen kann, ob der Server
die ursprüngliche Anfrage bekommen hat oder nicht.
Die Lösung ist entweder ein mysql_ping
auf der Verbindung, falls seit der letzten Abfrage viel Zeit
vergangen ist (so handelt auch MyODBC
),
oder eine Änderung von wait_timeout
auf
dem mysqld-Server auf einen Wert, der so
hoch ist, dass es praktisch nie zu einem Timeout kommt.
Solche Fehlermeldungen können Sie auch erhalten, wenn Sie
an den Server eine zu große oder eine falsche Anfrage
senden. Wenn mysqld ein Paket empfängt,
das zu groß oder nicht ordnungsgemäß ist, nimmt das
Programm an, dass mit dem Client etwas nicht stimmt, und
schließt die Verbindung. Wenn Sie große Anfragen
benötigen (zum Beispiel weil Sie mit umfangreichen
BLOB
-Spalten arbeiten), können Sie das
Limit pro Anfrage heraufsetzen, indem Sie die Servervariable
max_allowed_packet
von ihrem Standardwert
1 Mbyte auf etwas Höheres heraufsetzen. Vielleicht müssen
Sie auch die Paketgröße auf der Clientseite erhöhen.
Über die Einstellung der Paketgröße können Sie unter
Abschnitt A.2.9, „Packet too large
-Fehler“, mehr erfahren.
Ihre Verbindung wird auch abbrechen, wenn Sie ein Paket der Größe 16 Mbyte oder mehr verschicken und Ihr Client älter als Version 4.0.8 ist, während Ihr Server die Version 4.0.8 oder höher verwendet (oder umgekehrt).
Eventuell kommt es auch zu dem Fehler MySQL server
has gone away
, wenn MySQL mit der Option
--skip-networking
gestartet wird.
Während der Ausführung der Anfrage trat ein Fehler auf, der den Server angehalten hat.
Ob der MySQL Server abgestürzt und wieder hochgefahren ist, erfahren Sie, indem Sie mysqladmin version ausführen und auf die Uptime des Servers achten. Wenn die Clientverbindung unterbrochen war, weil mysqld abgestürzt und wieder hochgefahren ist, sollten Sie sich auf die Erforschung der Absturzursachen konzentrieren. Zuerst prüfen Sie, ob der Server bei derselben Anfrage erneut abstürzen wird. Siehe Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.
Mehr Informationen über unterbrochene Verbindungen bekommen
Sie, wenn Sie mysqld mit der Option
--log-warnings=2
starten. Damit werden einige
Verbindungsabbruchfehler in der Datei
hostname.err
protokolliert. Siehe
Abschnitt 5.12.1, „Die Fehler-Logdatei“.
Wenn Sie einen Bugreport über dieses Problem schicken möchten, senden Sie uns bitte auch folgende Informationen:
Angabe, ob der MySQL Server abgestürzt ist. Dies erfahren Sie aus dem Fehlerlog des Servers. Siehe Abschnitt A.4.2, „Was zu tun ist, wenn MySQL andauernd abstürzt“.
Wenn eine bestimmte Anfrage mysqld
anhält und die beteiligten Tabellen mit CHECK
TABLE
vor Ausführung dieser Anfrage überprüft
wurden: Können Sie dann einen reproduzierbaren Testfall
herstellen? Siehe Abschnitt E.1.6, „Erzeugen eines Testfalls, wenn Sie Tabellenbeschädigung feststellen“.
Welchen Wert hat die Systemvariable
wait_timeout
im MySQL Server? (Mit
mysqladmin variables erhalten Sie den
Wert dieser Variablen.)
Haben Sie versucht, mysqld mit der Option
--log
auszuführen, um festzustellen, ob
die Problemanfrage im Log auftaucht?
Siehe auch Abschnitt A.2.10, „Kommunikationsfehler/abgebrochene Verbindung“, und Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“.
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.
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“.
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=
die Größe der temporären Tabellen heraufsetzen oder
setzen die SQL-Option val
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 TABLEtbl_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.
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
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.
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
';
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
“.
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=
oder
charset_name
--with-extra-charsets=
ausführen. Siehe Abschnitt 2.8.2, „Typische configure-Optionen“.
charset_name
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.
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.
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.
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.
/tmp/mysql.sock
schützen oder ändern
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:
Sie melden sich als Administrator an.
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.
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
.
Öffnen Sie ein Konsolenfenster mit der DOS-Eingabeaufforderung:
Start -> Ausführen -> cmd
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
.
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.
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:
Sie melden sich als Unix- root
-User oder
als der Benutzer, unter dem der
mysqld-Server läuft, an.
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.
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
.
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.
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):
Halten Sie mysqld an und starten Sie ihn
erneut mit den Optionen --skip-grant-tables
--user=root
(Windows-Nutzer lassen
--user=root
weg).
Verbinden Sie sich mit folgendem Befehl mit dem mysqld-Server:
shell> mysql -u root
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.
Das neue Passwort sollte nun funktionieren.
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:
Starten Sie mysqld von gdb (oder einem anderen Debugger) aus. Siehe auch Abschnitt E.1.3, „mysqld unter gdb debuggen“.
Lassen Sie Ihre Testskripten laufen.
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
auf einen
bestimmten Thread umschalten, wobei
N
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.
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.
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.
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
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
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=
von mysqld_safe ein. Alternativ können Sie
die Umgebungsvariable timezone_name
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.
DATE
-SpaltenNULL
-Wertenalias
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
alle Spaltenwerte geliefert bekommen, die mit
col_name
LIKE
'a%'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_cscol_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.
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
mysql>tbl_name
(idate) VALUES (19970505);INSERT INTO
mysql>tbl_name
(idate) VALUES ('19970505');INSERT INTO
mysql>tbl_name
(idate) VALUES ('97-05-05');INSERT INTO
mysql>tbl_name
(idate) VALUES ('1997.05.05');INSERT INTO
mysql>tbl_name
(idate) VALUES ('1997 05 05');INSERT INTO
mysql>tbl_name
(idate) VALUES ('0000-00-00');SELECT idate FROM
mysql>tbl_name
WHERE idate >= '1997-05-05';SELECT idate FROM
mysql>tbl_name
WHERE idate >= 19970505;SELECT MOD(idate,100) FROM
mysql>tbl_name
WHERE idate >= 19970505;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.
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.
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 FROMtbl_name
GROUP BY root HAVING root > 0; SELECT id, COUNT(*) AS cnt FROMtbl_name
GROUP BY id HAVING cnt > 0; SELECT id AS 'Customer identity' FROMtbl_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.
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 TABLEtbl_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
“.
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.
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:
Testen Sie die Anfrage mit EXPLAIN
, um
offensichtliche Fehler zu finden. Siehe
Abschnitt 7.2.1, „EXPLAIN
-Syntax (Informationen über ein
SELECT
erhalten)“.
Wählen Sie nur diejenigen Spalten aus, die in der
WHERE
-Klausel aufgeführt sind.
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.
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.
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“.
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.
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.
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
können Sie die
Schlüsselverteilungen für die gescannte Tabelle
aktualisieren. Siehe auch Abschnitt 13.5.2.1, „tbl_name
ANALYZE TABLE
“.
Wenn Sie für die gescannte Tabelle die FORCE
INDEX
-Anweisung geben, teilen Sie MySQL dadurch mit,
dass Tabellenscans im Vergleich zur Verwendung des
vorgegebenen Indexes sehr aufwändig sind. Siehe
Abschnitt 13.2.7, „SELECT
“.
SELECT * FROM t1, t2 FORCE INDEX (index_for_column) WHERE t1.col_name=t2.col_name;
USE INDEX
und IGNORE
INDEX
können ebenfalls nützlich sein.
Globale und tabellenspezifische
STRAIGHT_JOIN
s. Siehe
Abschnitt 13.2.7, „SELECT
“.
Sie können auch globale oder Thread-spezifische
Systemvariablen einstellen, zum Beispiel indem Sie
mysqld mit der Option
--max-seeks-for-key=1000
starten oder dem
Optimierer mit SET max_seeks_for_key=1000
sagen, dass er davon ausgehen soll, dass kein Schlüsselscan
mehr als 1.000 Schlüsselsuchoperationen bedeutet. Siehe
Abschnitt 5.2.2, „Server-Systemvariablen“.
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-
oder
xxx
B-
in der
Gegend herumfliegt:
xxx
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-
mit den gewünschten Strukturänderungen.
xxx
Kopiere alle Zeilen der Originaltabelle in
A-
.
xxx
Benenne die Originaltabelle in
B-
um.
xxx
Gib A-
den ursprünglichen Namen der Tabelle.
xxx
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-
zurücklassen. Mit einer einfachen Umbenennung der
Tabellendateien auf Systemebene müssten Sie Ihre Daten
zurückbekommen.
xxx
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.
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
mysql>col_name1
,col_name2
,col_name3
FROMtbl_name
;SELECT
col_name1
,col_name3
,col_name2
FROMtbl_name
;
Wenn Sie dennoch die Reihenfolge der Spalten ändern möchten, tun Sie das folgendermaßen:
Sie erzeugen eine neue Tabelle, in der die Spalten die neue Reihenfolge haben.
Sie führen folgende Anweisung aus:
mysql>INSERT INTO new_table
->SELECT columns-in-new-order FROM old_table;
Sie löschen die old_table
oder benennen
sie um.
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.
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“.
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.
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=
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“.
old_host_name
-bin
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
statt in
host_name
.err
schreibt, damit Sie den Speicherplatz des alten Logs
leichter zurückholen können, indem Sie es einfach löschen
und mysqladmin refresh ausführen.
host_name
.log
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.