Anhang D. Anmerkungen zur Portierung auf andere Systeme

Inhaltsverzeichnis

D.1. Einen MySQL-Server debuggen
D.1.1. MySQL zum Debuggen kompilieren
D.1.2. Trace-Dateien erzeugen
D.1.3. mysqld unter gdb debuggen
D.1.4. Einen Stack-Trace benutzen
D.1.5. Log-Dateien benutzen, um Gründe für Fehler in mysqld zu finden
D.1.6. Einen Testfall herstellen, wenn Sie Tabellenbeschädigung feststellen
D.2. Einen MySQL-Client debuggen
D.3. Das DBUG-Paket
D.4. Sperrmethoden
D.5. Anmerkungen zu RTS-Thread
D.6. Unterschiede zwischen verschiedenen Thread-Paketen

Für den Server wird eine funktionierende Posix-Thread-Bibliothek benötigt. Auf Solaris 2.5 benutzen wir Sun PThread (die native Thread-Unterstützung in Version 2.4 und früher ist nicht gut genug). Auf Linux benutzen wir LinuxThread von Xavier Leroy, .

Der schwierige Teil der Portierung auf eine neue Unix-Variante ohne gute native Thread-Unterstützung ist wahrscheinlich, MIT-pThread zu portieren. Siehe with-pThread/README und POSIX-Thread programmieren.

Die MySQL-Distribution enthält eine gepatchte Version von Provenzanos PThread von MIT (siehe MIT-PThread-Website). Diese kann für einige Betriebssysteme benutzt werden, die kein POSIX-Thread haben.

Es ist ebenfalls möglich, ein anderes Thread-Paket auf Benutzerebene namens FSU-PThread zu benutzen (siehe FSU-PThread-Homepage). Diese Implementation wird für die SCO-Portierung benutzt.

In den thr_lock.c- und thr_alarm.c-Programmen im mysys-Verzeichnis finden Sie einige Tests / Beispiele dieser Probleme.

Sowohl Server als auch Client benötigen einen funktionierenden C++-Kompiler (wir benutzen gcc und haben SparcWorks ausprobiert). Ein anderer bekanntermaßen funktionierender Compiler ist Irix cc.

Um nur den Client zu kompilieren, benutzen Sie ./configure --without-server.

Es gibt momentan keine Unterstützung, um nur den Server zu kompilieren, noch ist es wahrscheinlich, dass eine solche hinzugefügt wird, falls nicht jemand einen guten Grund dafür findet.

Wenn Sie irgend welche Makefile oder das configure-Skript ändern wollen / müssen, müssen Sie sich Automake und Autoconf holen. Wir haben die automake-1.2- und autoconf-2.12-Distributionen benutzt.

Alle Schritte, die notwendig sind, um alles aus den grundlegendsten Dateien neu zu machen (make):

/bin/rm */.deps/*.P
/bin/rm -f config.cache
aclocal
autoheader
aclocal
automake
autoconf
./configure --with-debug=full --prefix='ihr_installationsverzeichnis'

# Die oben erzeugten makefiles benötigen GNU-make 3.75 oder neuer.
# (unten gmake genannt)
gmake clean all install init-db

Wenn Sie bei einer neuen Portierung Probleme bekommen, kann es sein, dass Sie MySQL etwas debuggen müssen! See Abschnitt D.1, „Einen MySQL-Server debuggen“.

HINWEIS: Bevor Sie mit dem Debuggen von mysqld anfangen, bringen Sie sich zuerst die Testprogramme mysys/thr_alarm und mysys/thr_lock zum Laufen. Das stellt sicher, dass Ihre Thread-Installation zumindest überhaupt eine Chance hat, zu funktionieren!

D.1. Einen MySQL-Server debuggen

Wenn Sie Funktionalität benutzen, die in MySQL sehr neu ist, können Sie versuchen, mysqld mit der --skip-new-Option laufen zu lassen (die alle sehr neue, potenziell unsichere Funktionalität abschaltet) oder mit --safe-mode, was viel an Optimierung abschaltet, die möglicherweise Probleme verursacht. See Abschnitt A.4.1, „Was zu tun ist, wenn MySQL andauernd abstürzt“.

Wenn mysqld nicht starten will, sollten Sie prüfen, ob Sie irgend welche my.cnf-Dateien haben, die mit Ihrer Konfiguration in Konflikt kommen! Sie können Ihre my.cnf-Argumente mit mysqld --print-defaults prüfen und sie vermeiden, indem Sie mit mysqld --no-defaults ... starten.

Wenn mysqld anfängt, Prozessorleistung oder Speicher zu fressen, oder wenn er ``hängt'', können Sie mysqladmin processlist status benutzen, um herauszufinden, ob irgend etwas eine Anfrage ausführt, die sehr lange dauert. Es ist eine gute Idee, mysqladmin -i10 processlist status in irgend einem Fenster laufen zu haben, wenn Sie Performance-Probleme oder Probleme damit haben, dass sich neue Clients nicht verbinden können.

Der Befehl mysqladmin debug dumpt Informationen über Sperren, die in Gebrauch sind, den benutzten Speicher und den Anfragengebrauch in die mysql-Log-Datei aus. Das kann helfen, einige Probleme zu lösen. Dieser Befehl stellt auch nützliche Informationen zur Verfügung, selbst wenn Sie MySQL nicht zum Debuggen kompiliert haben!

Wenn das Problem darin besteht, dass einige Tabellen langsamer und langsamer werden, sollten Sie versuchen, die Tabelle mit OPTIMIZE TABLE der myisamchk zu optimieren. See Kapitel 5, MySQL-Datenbankadministration. Sie sollten langsame Anfragen darüber hinaus mit EXPLAIN überprüfen.

Ebenfalls sollten Sie den Abschnitt über betriebssystemspezifische Dinge in diesem Handbuch lesen, weil Sie Probleme haben könnten, die einzigartig für Ihre Umgebung sind. See Abschnitt 3.6, „Betriebssystem-spezifische Anmerkungen“.

D.1.1. MySQL zum Debuggen kompilieren

Wenn Sie sehr spezielle Probleme haben, können Sie immer versuchen, MySQL zu debuggen. Dafür müssen Sie MySQL mit der --with-debug- oder der --with-debug=full-Option kompilieren. Sie können prüfen, ob MySQL mit Debuggen kompiliert wurde oder nicht, wenn Sie mysqld --help ausführen. Wenn das --debug-Flag in den Optionen aufgeführt ist, haben Sie Debuggen eingeschaltet. mysqladmin ver gibt die mysqld-Version in diesem Fall ebenfalls als mysql ... --debug aus.

Wenn Sie gcc oder egcs benutzen, ist die empfohlene configure-Zeile:

CC=gcc CFLAGS="-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql --with-debug --with-extra-charsets=complex

Das vermeidet Probleme mit der libstdc++-Bibliothek und mit C++-Ausnahmen (viele Compiler haben Probleme mit C++-Ausnahmen in threaded Code) und kompiliert eine MySQL-Version mit Unterstützung für alle Zeichensätze.

Wenn Sie einen Speicherüberlauffehler vermuten, können Sie MySQL mit --with-debug=full kompilieren, was zusätzlich einen (SAFEMALLOC)-Prüfer für die Speicherzuweisung installiert. Das Laufenlassen mit SAFEMALLOC ist jedoch recht langsam. Wenn Sie daher Performance-Probleme bekommen, sollten Sie mysqld mit der --skip-safemalloc-Option starten. Das schaltet die Speicherüberlaufprüfung für jeden Aufruf von malloc und free ab.

Wenn mysqld nicht mehr abstürzt, wenn Sie ihn mit --with-debug kompilieren, haben Sie wahrscheinlich einen Compiler-Bug oder einen Timing-Bug innerhalb von MySQL gefunden. In diesem Fall können Sie versuchen, -g für die CFLAGS- und CXXFLAGS-Variablen oben hinzuzufügen und nicht mehr --with-debug zu benutzen. Wenn mysqld jetzt stirbt, können Sie wenigstens mit gdb mit ihm verbinden oder gdb auf die Core-Datei benutzen, um herauszufinden, was passiert ist.

Wenn Sie MySQL zum Debuggen konfigurieren, können Sie viele zusätzliche Sicherheitprüffunktionen hinzufügen, die die Gesundheit von mysqld beobachten. Wenn Sie etwas ``Unerwartetes'' finden, wird ein Eintrag nach stderr geschrieben, den safe_mysqld in die Fehler-Log-Datei leitet! Das heißt auch, dass Sie bei unerwarteten Problemen mit MySQL und der Benutzung einer Quelldistribution als erstes MySQL zum Debuggen konfigurieren sollten! (Die zweite Sache wäre natürlich, eine E-Mail an zu schicken und um Hilfe zu bitten. Bitte benutzen Sie das mysqlbug-Skript für alle Bug-Berichte oder Fragen hinsichtlich der MySQL-Version, die Sie benutzen!

In der Windows-MySQL-Distribution wird mysqld.exe vorgabemäßig mit Unterstützung für Trace-Dateien kompiliert.

D.1.2. Trace-Dateien erzeugen

Wenn der mysqld-Server nicht startet oder wenn Sie den mysqld-Server schnell zum Absturz bringen können, können Sie versuchen, eine Trace-Datei zu erzeugen, um das Problem zu finden.

Hierfür brauchen Sie einen mysqld, der zum Debuggen kompiliert ist. Sie können das mit mysqld -V prüfen. Wenn die Versionsnummer mit -debug endet, ist Unterstützung für Trace-Dateien einkompiliert.

Starten Sie den mysqld-Server mit einem Trace-Log in /tmp/mysqld.trace (oder C:\mysqld.trace unter Windows):

mysqld --debug

Unter Windows sollten Sie auch den --standalone-Flag benutzen, um mysqld nicht als Systemdienst zu starten.

Machen Sie folgendes in einem DOS-Fenster:

mysqld --debug --standalone

Danach können Sie das mysql.exe-Kommandozeilenwerkzeug in einem zweiten DOS-Fenster benutzen, um das Problem zu reproduzieren. Sie können den obigen mysqld-Server mit mysqladmin shutdown herunter fahren.

Beachten Sie, dass die Trace-Datei sehr Groß wird! Wenn Sie eine kleinere Trace-Datei haben wollen, können Sie etwa folgendes tun:

mysqld --debug=d,info,error,query,general,where:O,/tmp/mysqld.trace

Das gibt nur Informationen für die interessantesten Dinge in /tmp/mysqld.trace aus.

Wenn Sie hierüber einen Bug-Bericht erstellen, schicken Sie bitte nur die Zeilen aus der Trace-Datei an die entsprechende Mailing-Liste, in denen etwas schief zu gehen scheint! Wenn Sie diese Stelle nicht finden können, können Sie die Trace-Datei per FTP einschicken, zusammen mit einem kompletten Bug-Bericht, an ftp://Support.mysql.com/pub/mysql/secret, so dass ein MySQL-Entwickler sich das ansehen kann.

Die Trace-Datei wird mit dem DBUG-Paket von Fred Fish hergestellt. See Abschnitt D.3, „Das DBUG-Paket“.

D.1.3. mysqld unter gdb debuggen

Auf den meisten Systemen können Sie mysqld von gdb starten, um mehr Informationen zu erhalten, wenn mysqld abstürzt.

Bei einigen älteren gdb-Versionen unter Linux müssen Sie run --one-thread benutzen, um den mysqld-Thread debuggen zu können. In diesem Fall können Sie zur gleichen Zeit nur einen Thread aktiv haben.

Wenn Sie mysqld unter gdb laufen lassen, sollten Sie den Stack-Trace mit --skip-stack-trace abschalten, um Segmentation-Fehler innerhalb gdb abfangen zu können.

Es ist sehr schwierig, MySQL unter gdb zu debuggen, wenn Sie permanent viele neue Verbindungen aufbauen, weil gdb den Speicher für den alten Thread nicht freigibt. Sie können dieses Problem vermeiden, indem Sie mysqld mit -O thread_cache_size= 'maximale_verbindungen +1' starten. In den meisten Fällen hilft bereits schon die Benutzung von -O thread_cache_size=5' recht viel!

Wenn Sie einen Coredump unter Linux erhalten wollen, wenn mysqld mit einem SIGSEGV-Signal stirbt, können Sie mysqld mit der --core-file-Option starten. Diese Core-Datei kann benutzt werden, um eine Zurückverfolgung (Backtrace) zu machen, die Ihnen helfen kann herauszufinden, warum mysqld starb:

shell> gdb mysqld core
gdb>   backtrace full
gdb>   exit

See Abschnitt A.4.1, „Was zu tun ist, wenn MySQL andauernd abstürzt“.

Wenn Sie gdb 4.17.x oder höher unter Linux benutzen, sollten Sie eine .gdb-Datei mit folgenden Informationen in Ihrem aktuellen Verzeichnis installieren:

set print sevenbit off
handle SIGUSR1 nostop noprint
handle SIGUSR2 nostop noprint
handle SIGWAITING nostop noprint
handle SIGLWP nostop noprint
handle SIGPIPE nostop
handle SIGALRM nostop
handle SIGHUP nostop
handle SIGTERM nostop noprint

Wenn Sie Probleme haben, den Thread mit gdb zu debuggen, sollten Sie gdb 5.x herunter laden und diesen statt dessen benutzen. Die neue gdb-Version hat eine stark verbesserte Thread-Handhabung!

Hier ist ein Beispiel, wie man mysqld debuggt:

shell> gdb /usr/local/libexec/mysqld
gdb> run
...
backtrace full # Tun Sie das, wenn mysqld abstürzt

Schließen Sie die obige Ausgabe in eine Mail ein, die mit mysqlbug erzeugt wurde und schicken Sie sie an mysql@lists.mysql.com.

Wenn mysqld hängen bleibt, können Sie versuchen, einige Systemwerkzeuge wie strace oder /usr/proc/bin/pstack zu benutzen, um herauszufinden, was mysqld zum Hängen brachte.

strace /tmp/log libexec/mysqld

Wenn Sie die Perl-DBI-Schnittstelle benutzen, können Sie Debug-Informationen anschalten, indem Sie die trace-Methode benutzen oder die DBI_TRACE-Umgebungsvariable setzen. See Abschnitt 9.2.2, „Die DBI-Schnittstelle“.

D.1.4. Einen Stack-Trace benutzen

Auf manchen Betriebssystemen enthält die Fehler-Log-Datei einen Stack-Trace, wenn mysqld unerwartet stirbt. Diese können Sie benutzen, um herauszufinden, wo (und vielleicht warum) mysqld starb. See Abschnitt 5.9.1, „Die Fehler-Log-Datei“. Um einen Stack-Trace zu erhalten, sollten Sie mysqld NICHT mit der -fomit-frame-pointer-Option für gcc kompilieren. See Abschnitt D.1.1, „MySQL zum Debuggen kompilieren“.

Wenn die Fehlerdatei etwas wie folgendes enthält:

mysqld got signal 11;
The manual section 'debugging a MySQL server' tells you how to use a
stack trace and/or the core file to produce a readable backtrace that may
help in finding out why mysqld died
Attemping backtrace. You can use the following information to find out
where mysqld died.  Wenn you see no messages after this, something went
terribly wrong
stack range sanity check, ok, backtrace follows
0x40077552
0x81281a0
0x8128f47
0x8127be0
0x8127995
0x8104947
0x80ff28f
0x810131b
0x80ee4bc
0x80c3c91
0x80c6b43
0x80c1fd9
0x80c1686

Können Sie herausfinden, wo mysqld starb, indem Sie folgendes tun:

  1. Kopieren Sie die obigen Zahlen in eine Datei, zum Beispiel mysqld.stack.

  2. Machen Sie eine symbolische Datei für den mysqld-Server:

    nm -n libexec/mysqld > /tmp/mysqld.sym
    

    Beachten Sie, dass viele MySQL-Binärdistributionen die obige Datei namens mysqld.sym.gz enthalten. In diesem Fall müssen Sie sie wie folgt entpacken:

    gunzip < bin/mysqld.sym.gz > /tmp/mysqld.sym
    

  3. Führen Sie resolve_stack_dump -s /tmp/mysqld.sym -n mysqld.stack aus.

    Das gibt aus, wo mysqld starb. Wenn Ihnen das nicht hilft, herauszufinden, warum mysqld starb, sollten Sie einen Bug-Bericht machen und die Ausgabe des obigen Befehls in diesen Bericht einschließen.

    Beachten Sie aber, dass es uns in den meisten Fällen nicht weiterhilft, nur einen Stack-Trace zu haben, um die Ursache des Problems herauszufinden. Um den Bug feststellen oder einen Workaround zur Verfügung stellen zu können, müssen wir in den meisten Fällen die Anfrage kennen, die mysqld tötete, und am besten einen Testfall, so dass wir das Problem wiederholen können! See Abschnitt 2.6.2.3, „Wie man Bugs oder Probleme berichtet“.

D.1.5. Log-Dateien benutzen, um Gründe für Fehler in mysqld zu finden

Beachten Sie, dass Sie vor dem Start von mysqld mit --log alle Ihre Tabellen mit myisamchk prüfen sollten. See Kapitel 5, MySQL-Datenbankadministration.

Wenn mysqld stirbt oder hängenbleibt, sollten Sie ihn mit --log starten. Wenn mysqld wieder stirbt, können Sie das Ende der Log-Datei nach der Anfrage durchsuchen, die mysqld tötete.

Wenn Sie --log ohne einen Dateinamen verwenden, wird das Log im Datenbank-Verzeichnis als 'hostname'.log gespeichert. In den meisten Fällen ist es die letzte Anfrage in der Log-Datei, die mysqld tötete, aber das sollten Sie falls möglich sicherstellen, indem Sie mysqld neu starten und dieselbe Anfrage mit dem mysql-Kommandozeilenwerkzeug wiederholen. Wenn das funktioniert, sollten Sie ebenfalls alle komplizierten Anfragen testen, die nicht beendet wurden.

Sie können auch den Befehl EXPLAIN auf alle SELECT-Statements ausprobieren, die lange Zeit benötigen, um sicherzustellen, dass mysqld Indexe korrekt benutzt. See Abschnitt 6.2.1, „EXPLAIN-Syntax (Informationen über ein SELECT erhalten)“.

Sie finden Anfragen, die zur Ausführung lange Zeit benötigen, indem Sie mysqld mit --log-slow-queries starten. See Abschnitt 5.9.5, „Die Anfragen-Log-Datei für langsame Anfragen“.

Wenn Sie den Text mysqld restarted in der Fehler-Log-Datei-Datei (normalerweise namens hostname.err) finden, haben Sie wahrscheinlich eine Anfrage gefunden, die mysqld zum Absturz brachte. Wenn das passiert, sollten Sie alle Ihre Tabellen mit myisamchk prüfen (see Kapitel 5, MySQL-Datenbankadministration) und die Anfragen in den MySQL-Log-Dateien untersuchen, um herauszufinden, ob eine nicht funktioniert. Wenn Sie eine solche Anfrage finden, versuchen Sie zunächst, auf die neueste MySQL-Version zu aktualisieren. Wenn das nicht hilft und Sie nichts im mysql-Mailarchiv finden können, sollten Sie den Bug an berichten. Links zu Mailarchiven finden Sie online auf der MySQL-Dokumentationsseite.

Wenn Sie mysqld mit --with-myisam-recover gestartet haben, prüft MySQL automatisch MyISAM-Tabellen und versucht sie zu reparieren, wenn sie als 'nicht korrekt geschlossen' oder 'beschädigt' gekennzeichnet sind. Wenn das passiert, schreibt MySQL einen Eintrag in die hostname.err-Datei 'Warning: Checking table ...', der von Warning: Repairing table gefolgt wird, wenn die Tabelle repariert werden muss. Wenn Sie viele solcher Fehler erhalten, ohne dass mysqld direkt davor unerwartet gestorben ist, stimmt etwas nicht und muss weiter untersucht werden. See Abschnitt 5.1.1, „mysqld-Kommandozeilenoptionen“.

Natürlich ist es kein gutes Zeichen, wenn mysqld unerwartet stirbt, doch in diesem Fall sollte man nicht die Checking table...-Meldungen untersuchen, sondern statt dessen versuchen herauszufinden, warum mysqld starb.

D.1.6. Einen Testfall herstellen, wenn Sie Tabellenbeschädigung feststellen

Wenn Sie beschädigte Tabellen erhalten oder wenn mysqld immer nach irgend einem Aktualisierungsbefehl fehlschlägt, können Sie mit folgendem überprüfen, ob der Bug reproduzierbar ist:

  • Fahren Sie den MySQL-Daemon herunter (mit mysqladmin shutdown).

  • Machen Sie eine Datensicherung der Tabellen (um dem sehr unwahrscheinlichen Fall vorzubeugen, dass die Reparatur etwas Schlechtes macht).

  • Prüfen Sie alle Tabellen mit myisamchk -s Datenbank/*.MYI. Reparieren Sie jegliche beschädigten Tabellen mit myisamchk -r datenbank/tabelle.MYI.

  • Machen Sie eine Datensicherung der Tabellen.

  • Entfernen (oder verschieben) Sie jegliche alten Log-Dateien aus dem MySQL-Daten-Verzeichnis, wenn Sie mehr Platz brauchen.

  • Starten Sie mysqld mit --log-binary. See Abschnitt 5.9.4, „Die binäre Update-Log-Datei“. Wenn Sie eine Anfrage finden wollen, die mysqld zum Absturz brachte, sollten Sie --log --log-binary benutzen.

  • Wenn Sie eine beschädigte Tabelle erhalten, halten Sie mysqld an.

  • Stellen Sie die Datensicherung wieder her.

  • Starten Sie den mysqld-Server neu, ohne --log-binary.

  • Führen Sie die Befehle mit mysqlbinlog update-log-file | mysql erneut aus. Die Update-Log-Datei wird im MySQL-Datenbank-Verzeichnis unter dem Namen hostname-bin.# gespeichert.

  • Wenn die Tabellen wieder beschädigt werden oder Sie mysqld wieder dazu bringen können zu sterben, haben Sie einen reproduzierbaren Bug gefunden, der sich leicht beheben lassen sollte! Schicken Sie die Tabellen und die Binär-Log-Datei an ftp://support.mysql.com/pub/mysql/secret und schicken Sie eine E-Mail an oder (wenn Sie ein Support-Kunde sind) an , und das MySQL-Team wird den Bug so schnell wie möglich beheben.

Sie können auch das Skript mysql_find_rows benutzen, um einfach einige der Aktualisierungs-Statements auszuführen, wenn Sie das Problem eingrenzen wollen.

D.2. Einen MySQL-Client debuggen

Um einen MySQL-Client mit dem integrierten Debug-Paket debuggen zu können, sollten Sie MySQL mit --with-debug oder --with-debug=full kompilieren. See Abschnitt 3.3.3, „Typische configure-Optionen“.

Bevor Sie einen Client laufen lassen, sollten Sie die MYSQL_DEBUG-Umgebungsvariable setzen:

shell> MYSQL_DEBUG=d:t:O,/tmp/client.trace
shell> export MYSQL_DEBUG

Das bringt Clients dazu, eine Trace-Datei in /tmp/client.trace zu erzeugen.

Wenn Sie Probleme mit Ihrem eigenen Client-Code haben, sollten Sie versuchen, sich mit dem Server zu verbinden und Ihre Anfragen mit einem Client laufen zu lassen, der bekanntermaßen funktioniert. Lassen Sie dabei mysql im Debug-Modus laufen (unter der Annahme, dass Sie MySQL mit angeschaltetem Debuggen kompiliert haben):

shell> mysql --debug=d:t:O,/tmp/client.trace

Das stellt nützliche Informationen für den Fall bereit, dass Sie einen Bug-Bericht schicken. See Abschnitt 2.6.2.3, „Wie man Bugs oder Probleme berichtet“.

Wenn Ihr Client bei irgend einem 'zulässigen' Sperr-Code abstürzt, sollten Sie sicherstellen, dass Ihre mysql.h-Include-Datei mit Ihrer MySQL-Bibliotheksdatei zusammenpasst. Es ist ein häufiger Fehler, eine alte mysql.h-Datei aus einer alten MySQL-Installation mit einer neuen MySQL-Bibliothek zu benutzen.

D.3. Das DBUG-Paket

Der MySQL-Server und die meisten MySQL-Clients werden mit dem DBUG-Paket kompiliert, das ursprünglich von Fred Fish stammt. Wenn man MySQL zum Debuggen kompiliert hat, ermöglicht es dieses Paket, eine Trace-Datei davon zu erhalten, was das Programm debuggt. See Abschnitt D.1.2, „Trace-Dateien erzeugen“.

Man benutzt das Debug-Paket durch Aufruf des Programms mit der --debug="..."- oder der -#...-Option.

Die meisten MySQL-Programme haben eine vorgabemäßige Debug-Zeichenkette, die benutzt wird, wenn Sie keine Option für --debug angeben. Die vorgabemäßige Trace-Datei ist üblicherweise /tmp/programm_name.trace unter Unix und \programm_name.trace unter Windows.

Die Debug-Steuerungs-Zeichenkette ist eine Folge durch Doppelpunkte getrennter Felder, wie folgt:

<feld_1>:<feld_2>:...:<feld_N>

Jedes Feld besteht aus einem zwingend erforderlichen Flag-Zeichen, gefolgt durch ein optionales Komma (",") und eine durch Kommas getrennte Auflistung von Modifikatoren:

flag[,modifikator,modifikator,...,modifikator]

Aktuell werden folgende Flag-Zeichen erkannt:

dAusgabe von DBUG_<N>-Makros des aktuellen Status ermöglichen. Gegebenenfalls gefolgt von einer Auflistung von Schlüsselwörtern, die Ausgaben nur für die DBUG-Makros mit diesem Schlüsselwort auswählt. Eine leere Auflistung von Schlüsselwörtern bedeutet Ausgabe für alle Makros.
DNach jeder Debugger-Ausgabezeile verzögern. Das Argument ist die Anzahl von Zehntelsekunden der Verzögerung, abhängig von den Fähigkeiten der Maschine. -#D,20 bedeutet als eine Verzögerung von 2 Sekunden.
fDebuggen und / oder Tracen und Profilen auf die in der Auflistung genannten Funktionen beschränken. Beachten Sie, dass eine leere Liste alle Funktionen abschaltet. Die entsprechenden "d"- oder "t"-Flags müssen immer noch angegeben werden; dieser Flag beschränkt nur ihre Aktionen, wenn Sie angeschaltet sind.
FDen Quell-Dateinamen für jede Zeile der Debug- oder Trace-Ausgabe festlegen.
iDen Prozess mit der PID- oder Thread-Kennung für jede Ziele der Debug- oder Trace-Ausgabe festlegen.
gProfiling anschalten. Es wird eine Datei namens 'dbugmon.out' erzeugt, die Informationen enthält, die benutzt werden können, um das Programm zu profilen. Wir gegebenenfalls von einer Auflistung von Schlüsselwörter gefolgt, die Profiling nur für die Funktionen in dieser Liste auswählen. Eine leere Liste bedeutet, dass alle Funktionen in Betracht gezogen werden.
LDie Quell-Datei-Zeilennummer für jede Zeile der Debug- oder Trace-Ausgabe festlegen.
nDie aktuelle Funktionsverschachtelungstiefe für jede Zeile der Debug- oder Trace-Ausgabe ausgeben.
NJede Zeile der dbug-Ausgabe nummerieren.
oDie Debugger-Ausgabe in die angegebene Datei umlenken. Die vorgabemäßige Ausgabe ist stderr.
OWie O, aber die Datei wird nach jedem Schreiben auf die Platte zurückgeschrieben (flush). Wenn nötig, wird die Datei geschlossen und wieder geöffnet.
pDebugger-Aktionen auf die angegebenen Prozesse beschränken. Ein Prozess muss mit dem DBUG_PROCESS-Makro gekennzeichnet sein und mit einer der Aktionen in der Liste übereinstimmen, damit Debugger-Aktionen durchgeführt werden.
PDen aktuellen Prozessnamen für jede Zeile der Debug- oder Trace-Ausgabe ausgeben.
rWenn ein neuer Zustand gepusht wird, nicht die Funktionsverschachtelungsebene des alten Zustands übernehmen (erben). Nützlich, wenn die Ausgabe am linken Rand anfangen soll.
SFunktion _sanity(_datei_,_zeile_) bei jeder debuggten Funktion ausführen, bis _sanity() etwas anderes als 0 zurückgibt. (Wird meist zusammen mit safemalloc benutzt, um Speicherlecks zu finden.)
tTrace-Zeile für Funktionsaufrufen / Funktionsende anschalten. Wird gegebenenfalls gefolgt von einer Liste (die nur einen Modifikator enthält), in der numerisch eine maximale Trace-Ebene angegeben wird, nach der keine Ausgaben mehr erfolgen, weder für Debuggen noch für das Tracen von Makros. Die Vorgabe ist eine Kompilierzeit-Option.

Einige Beispiele von Debug-Steuerungs-Zeichenketten, die auf einer Shell-Kommandozeile erscheinen können (das "-#" wird typischerweise benutzt, um eine Steuerungs-Zeichenkette für ein Applikationsprogramm einzuführen):

-#d:t
-#d:f,main,subr1:F:L:t,20
-#d,input,output,files:n
-#d:t:i:O,\\mysqld.trace

In MySQL werden gebräuchlicherweise (mit der d-Option) folgende Tags ausgegeben: enter, exit, error, warning, info und loop.

D.4. Sperrmethoden

Momentan unterstützt MySQL Tabellensperren nur für ISAM- / MyISAM- und HEAP-Tabellen und Sperren auf Seitenebene nur für BDB-Tabellen. See Abschnitt 6.3.1, „Wie MySQL Tabellen sperrt“. Bei MyISAM-Tabellen können Sie INSERT und SELECT ohne Sperren frei vermischen. (Versionierung).

Ab Version 3.23.33 können Sie die Tabellensperr-Konkurrenz auf Ihrem System durch Prüfen der Table_locks_waited- und Table_locks_immediate-Umgebungsvariablen analysieren.

Einige Datenbankbenutzer behaupten, dass MySQL keine große Anzahl gleichzeitiger Benutzer unterstützen kann, weil es kein Sperren auf Zeilenebene hat. Das mag bei einigen speziellen Applikationen zutreffen, aber nicht allgemein. Wie immer hängt das völlig davon ab, was Ihre Applikation macht, und davon, wie das Zugriffs-/Aktualisierungs-Muster der Daten aussieht.

Vorteile für Zeilensperren:

  • Weniger Sperrkonflikte beim Zugriff auf unterschiedliche Zeilen in vielen Threads.

  • Weniger Änderungen bei Rollbacks.

  • Macht es möglich, eine einzelne Zeile lange zu sperren.

Nachteile:

  • Benötigt mehr Speicher als Sperren auf Seiten- oder Tabellenebene.

  • Ist langsamer als Sperren auf Seiten- oder Tabellenebene, wenn es einen großen Teil der Tabelle betrifft, weil man viel mehr Sperren durchführen muss.

  • Ist definitiv viel schlechter als andere Sperren, wenn Sie oft GROUP BY auf einen großen Teil der Daten ausführen oder wenn man die gesamte Tabelle oft scannen muss.

  • Bei Sperren auf höherer Ebene kann man einfacher Sperren unterschiedlichen Typs unterstützen, um die Applikation zu optimieren, weil der Sperr-Overhead sich weniger als bei Sperren auf Zeilenebene bemerkbar macht.

Tabellensperren sind Seiten- oder Zeilensperren in folgenden Fällen überlegen:

  • Wenn man meist liest.

  • Wenn Lese- und Aktualisierungsoperationen auf strengen Schlüsseln erfolgen. Das ist dann der Fall, wenn man eine Zeile aktualisiert oder löscht, die mit einem Schlüssel-Lesen geholt werden kann:

    UPDATE tabelle SET spalte=wert WHERE eindeutige_schluessel_nummer
    DELETE FROM tabelle WHERE eindeutiger_schluessel=#
    

  • SELECT in Kombination mit INSERT (und sehr wenigen UPDATE's und DELETE's).

  • Viele Scans / GROUP BY auf die gesamte Tabelle ohne irgend welche Schreibvorgänge.

Andere Optionen als Sperren auf Zeilen- / Seiten-Ebene:

Versionierung (wie die, die wir bei MySQL für gleichzeitige Einfügevorgänge nutzen), bei der man gleichzeitig einen Schreibvorgang haben kann, während viele Lesevorgänge stattfinden. Das heißt, dass die Datenbank / Tabelle verschiedene Sichten der Daten unterstützt, abhängig davon, wann man anfing, darauf zuzugreifen. Andere Namen hierfür sind Zeitreisen, Kopieren beim Schreiben (Copy on Write) oder Kopieren bei Bedarf (Copy on Demand).

Kopieren bei Bedarf ist in vielen Fällen viel besser als Sperren auf Seiten- oder Zeilenebene. Im schlimmsten Fall wird jedoch viel mehr Speicher verbraucht als bei der Benutzung normaler Sperren.

Anstelle von Zeilen-Sperren kann man Sperren auf Applikationsebene benutzen (wie get_lock/release_lock in MySQL). Das funktioniert natürlich nur bei 'wohl erzogenen' Applikationen.

In vielen Fällen kann man auf fortgeschrittene Art raten, welcher Sperrtyp der beste für die Applikation ist, aber allgemein ist es sehr schwer zu sagen, dass ein bestimmter Sperrtyp besser ist als ein anderer. Alles hängt von der Applikation ab, und verschiedene Teile der Applikation können nach unterschiedlichen Sperrtypen verlangen.

Hier sind einige Tipps zu Sperren in MySQL:

Bei Web-Applikation führen die meisten Applikationen viele SELECTs aus, sehr wenige DELETEs, UPDATEs hauptsächlich auf Schlüssel und INSERTs in einigen bestimmten Tabellen. Die grundlegende Einrichtung von MySQL ist hierfür BESTENS optimiert.

Gleichzeitige Benutzer sind kein Problem, solange man UPDATEs und SELECTs nicht vermischt, die beide gleichzeitig viele Zeilen in derselben Tabelle untersuchen müssen.

Wenn man INSERTs und DELETEs auf dieselbe Tabelle mischt, kann INSERT DELAYED eine große Hilfe sein.

Man kann auch LOCK TABLES benutzen, um Dinge zu beschleunigen (viele UPDATEs innerhalb einer einzelnen Sperre sind viel schneller als UPDATEs ohne Sperren). Daten in unterschiedliche Tabellen aufteilen hilft hierbei auch.

Wenn Sie Geschwindigkeitsprobleme mit den Tabellensperren in MySQL bekommen, können Sie diese eventuell dadurch lösen, dass Sie Ihre Tabellen in BDB-Tabellen umwandeln. See Abschnitt 8.6, „BDB- oder Berkeley_db-Tabellen“.

Der Optimierungsabschnitt dieses Handbuchs behandelt viele verschiedene Aspekte dessen, wie man seine Applikationen optimieren kann. See Abschnitt 6.2.11, „Weitere Optimierungstipps“.

D.5. Anmerkungen zu RTS-Thread

Ich habe versucht, die RTS-Thread-Pakete bei MySQL zu benutzen, bin aber über folgende Probleme gestolpert:

Sie benutzen die alte Version vieler POSIX-Aufrufe und es ist sehr mühsam, Wrapper für alle Funktionen zu schreiben. Ich neige dazu zu denken, dass es leichter ist, die Thread-Bibliotheken auf die neueste POSIX-Spezifikation zu ändern.

Einige Wrapper sind bereits geschrieben. Siehe mysys/my_pThread.c wegen weiterer Informationen.

Zumindest folgendes sollte geändert werden:

pthread_get_specific sollte ein Argument benutzen. sigwait sollte zwei Argumente entgegennehmen. Viele Funktionen (zumindest pthread_cond_wait und pthread_cond_timedwait) sollten bei einem Fehler den Fehler-Code zurückgeben. Momentan geben sie -1 zurück und setzen errno.

Ein weiteres Problem ist, dass Threads auf Benutzerebene das ALRM-Signal benutzen und dass dieses viele Funktionen abbricht (read, write, open, ...). MySQL sollte versuchen, nach der Unterbrechung all dieser Funktionen weiterzumachen, aber das ist nicht einfach zu verifizieren.

Das größte ungelöste Problem ist folgendes:

Um Alarme auf Thread-Ebene zu erhalten, änderte ich mysys/thr_alarm.c in der Art, dass es zwischen Alarmen wartet, mit pthread_cond_timedwait(), aber das bricht mit Fehler EINTR ab. Ich versuchte, die Thread-Bibliothek zu debuggen, um den Grund herauszufinden, konnte aber keine einfache Lösung finden.

Wenn jemand MySQL mit RTS-Thread ausprobieren möchte, schlage ich folgendes vor:

  • Funktionen, die MySQL benutzt, von der Thread-Bibliothek zu POSIX ändern. Das sollte nicht lange dauern.

  • Alle Bibliotheken mit -DHAVE_rts_thread kompilieren.

  • thr_alarm kompilieren.

  • Wenn es kleine Unterschiede in der Implementation gibt, können diese behoben werden, indem man my_pThread.h und my_pThread.c ändert.

  • thr_alarm laufen lassen. Wenn es ohne irgend welche ``warning''-, ``error''- oder ``aborted''-Meldungen läuft, sind Sie auf dem richtigen Weg. Hier ist ein erfolgreiches Laufenlassen unter Solaris:

    Main Thread: 1
    Thread 0 (5) started
    Thread: 5  Waiting
    process_alarm
    Thread 1 (6) started
    Thread: 6  Waiting
    process_alarm
    process_alarm
    thread_alarm
    Thread: 6  Slept for 1 (1) sec
    Thread: 6  Waiting
    process_alarm
    process_alarm
    thread_alarm
    Thread: 6  Slept for 2 (2) sec
    Thread: 6  Simulation of no alarm needed
    Thread: 6  Slept for 0 (3) sec
    Thread: 6  Waiting
    process_alarm
    process_alarm
    thread_alarm
    Thread: 6  Slept for 4 (4) sec
    Thread: 6  Waiting
    process_alarm
    thread_alarm
    Thread: 5  Slept for 10 (10) sec
    Thread: 5  Waiting
    process_alarm
    process_alarm
    thread_alarm
    Thread: 6  Slept for 5 (5) sec
    Thread: 6  Waiting
    process_alarm
    process_alarm
    
    ...
    thread_alarm
    Thread: 5  Slept for 0 (1) sec
    end
    

D.6. Unterschiede zwischen verschiedenen Thread-Paketen

MySQL ist sehr abhängig vom verwendeten Thread-Paket. Wenn Sie daher eine gute Plattform für MySQL auswählen, ist das Thread-Paket sehr wichtig.

Es gibt mindestens drei Typen von Thread-Paketen:

  • Benutzer-Thread in einem einzelnen Prozess. Das Thread-Umschalten wird mit Alarmen gemacht und die Thread-Bibliothek verwaltet alle nicht Thread-sicheren Funktionen mit Sperren. Lese-, Schreib- und Auswahl-Operationen werden üblicherweise mit einer Thread-spezifischen Auswahl verwaltet, die auf einen anderen Thread umschaltet, wenn der laufende Thread auf Daten warten muss. Wenn die Benutzer-Thread-Pakete in die Standard-Bibliotheken integriert sind (FreeBSD- und BSDI-Thread), erfordert das Thread-Paket weniger Overhead als Thread-Pakete, die alle unsicheren Aufrufen mappen müssen (MIT-pThread, FSU-PThread und RTS-Thread). In einigen Umgebungen (beispielsweise SCO) sind alle Systemaufrufe Thread-sicher, weshalb das Mapping sehr leicht durchgeführt werden kann (FSU-PThread unter SCO). Nachteil: Alle gemappten Aufrufe benötigen etwas Zeit und es ist sehr verzwickt, alle Situationen handhaben zu können. Üblicherweise gibt es auch einige Systemaufrufe, die vom Thread-Paket nicht gehandhabt werden (wie MIT-pThread und Sockets). Thread-Scheduling ist nicht immer optimal.

  • Benutzer-Thread in separaten Prozessen. Das Thread-Umschalten wird vom Kernel durchgeführt und alle Daten werden zwischen den Threads geteilt. Das Thread-Paket verwaltet die Standard-Thread-Aufrufe, so dass diese Daten zwischen Threads teilen können. LinuxThread benutzt diese Methode. Nachteil: viele Prozesse. Die Erzeugung von Threads ist langsam. Wenn ein Thread stirbt, bleiben die übrigen üblicherweise hängen, und Sie müssen alle töten, bevor Sie neu starten können. Man kann sagen, dass die Thread-Umschaltung ziemlich viel kostet.

  • Kernel-Thread. Das Thread-Umschalten wird von der Thread-Bibliothek oder dem Kernel durchgeführt und ist sehr schnell. Alles wird in einem Prozess gemacht, aber auch manchen Systemen zeigt ps die verschiedenen Threads. Wenn ein Thread abbricht, bricht der gesamte Prozess ab. Die meisten Systemaufrufe sind Thread-sicher und sollten sehr wenig Overhead beanspruchen. Solaris, HP-UX, AIX und OSF1 haben Kernel-Thread.

Auf manchen Systemen wird Kernel-Thread gehandhabt, indem Benutzerebenen-Thread in die Systembibliotheken integriert wird. In solchen Fällen kann das Umschalten nur von der Thread-Bibliothek durchgeführt werden und der Kernel ist sich nicht wirklich ``der Threads bewusst''.


This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.