Die Clientbibliothek ist beinahe Thread-sicher. Das größte
Problem besteht darin, dass die Subroutinen in
net.c
, die Daten aus Sockets lesen, nicht
gegen Interrupts gesichert sind. Dies wurde mit dem
Hintergedanken so eingerichtet, dass Sie vielleicht einen
eigenen Alarm installieren möchten, der einen langen
Lesevorgang auf einem Server abbrechen kann. Wenn Sie
Interrupt-Handler für den SIGPIPE
-Interrupt
installieren, sollte die Arbeit auf dem Socket Thread-sicher
sein.
Um zu verhindern, dass das Programm abbricht, sobald eine
Verbindung endet, blockiert MySQL SIGPIPE
beim ersten Aufruf von mysql_server_init()
,
mysql_init()
oder
mysql_connect()
. Wenn Sie einen eigenen
SIGPIPE
-Handler benutzen möchten, sollten
Sie als Erstes mysql_server_init()
aufrufen
und dann Ihren Handler installieren.
In den älteren Binaries, die auf unserer Website angeboten werden (http://www.mysql.com/), werden die Clientbibliotheken normalerweise nicht mit der Thread-sicheren Option kompiliert (ausgenommen die Windows-Binaries, die standardmäßig Thread-sicher kompiliert werden). Neuere Binärdistributionen sollten sowohl eine normale als auch eine Thread-sichere Clientbibliothek besitzen.
Um einen Threaded Client zu erstellen, den Sie mit anderen
Threads unterbrechen und auf dem Sie Timeouts für die
Kommunikation mit dem MySQL Server einstellen können, verwenden
Sie die Bibliotheken -lmysys
,
-lmystrings
und -ldbug
sowie
den net_serv.o
-Code, den auch der Server
benutzt.
Wenn Sie keine Interrupts oder Timeouts benötigen, kompilieren
Sie einfach eine Thread-sichere Clientbibliothek
(mysqlclient_r)
und benutzen diese. Siehe
Abschnitt 24.2, „MySQL-C-API“. In diesem Fall müssen Sie sich über die
net_serv.o
-Objektdatei oder die anderen
MySQL-Bibliotheken keine Gedanken machen.
Wenn Sie einen Threaded Client mit Timeouts und Interrupts
benutzen möchten, sind die Routinen in der Datei
thr_alarm.c
sehr gut geeignet. Benutzen Sie
Routinen aus der mysys
-Bibliothek, so müssen
Sie nur daran denken, my_init()
immer als
Erstes aufzurufen! Siehe Abschnitt 24.2.11, „C-Threaded-Funktionsbeschreibungen“.
Alle Funktionen außer mysql_real_connect()
sind standardmäßig Thread-sicher. Die folgenden Hinweise
beschreiben, wie man eine Thread-sichere Clientbibliothek
kompiliert und in Thread-sicherer Weise benutzt. (Eigentlich
gelten die folgenden Hinweise zu
mysql_real_connect()
auch für
mysql_connect()
, aber da
mysql_connect()
veraltet ist, sollten Sie
ohnehin nur mit mysql_real_connect()
arbeiten.)
Um mysql_real_connect()
Thread-sicher zu
machen, müssen Sie die Clientbibliothek mit folgendem Befehl
neu kompilieren:
shell> ./configure --enable-thread-safe-client
Dies erzeugt die Thread-sichere Clientbibliothek
libmysqlclient_r
. (Immer vorausgesetzt, dass
Ihr Betriebssytem über eine Thread-sichere
gethostbyname_r()
-Funktion verfügt.) Diese
Bibliothek ist pro Verbindung Thread-sicher. Zwei Threads
können also dieselbe Verbindung nutzen, allerdings mit
folgenden Schwachstellen:
Zwei Threads können einem MySQL Server nicht gleichzeitig
über dieselbe Verbindung eine Anfrage senden. Sie müssen
vor allem gewährleisten, dass zwischen
mysql_query()
und
mysql_store_result()
kein anderer Thread
dieselbe Verbindung benutzt.
Viele Threads können auf unterschiedliche Ergebnismengen
zugreifen, die mit mysql_store_result()
abgerufen werden.
Wenn Sie dagegen mysql_use_result
benutzen, müssen Sie dafür sorgen, dass so lange kein
anderer Thread dieselbe Verbindung benutzt, bis die
Ergebnismenge wieder geschlossen wurde. Allerdings ist
mysql_store_result()
ohnehin die bessere
Lösung für Threaded Clients, die sich dieselbe Verbindung
teilen.
Wenn Sie mehrere Threads auf derselben Verbindung einsetzen
möchten, müssen Sie die mysql_query()
-
und
mysql_store_result()
-Aufrufkombinationen
mit einer Mutex-Sperre umgeben. Sobald
mysql_store_result()
fertig ist, kann die
Sperre aufgehoben werden und andere Threads können Anfragen
an dieselbe Verbindung schicken.
Wenn Sie mit POSIX-Threads programmieren, können Sie mit
pthread_mutex_lock()
und
pthread_mutex_unlock()
eine Mutex-Sperre
errichten und wieder freigeben.
Folgendes ist wichtig, wenn Sie einen Thread andere MySQL-Funktionen aufrufen lassen als die, welche die Verbindung zur MySQL-Datenbank eingerichtet haben:
Wenn Sie mysql_init()
oder
mysql_connect()
aufrufen, legt MySQL eine
Thread-spezifische Variable für den Thread an, die (unter
anderem) von der Debugbibliothek genutzt wird.
Wenn Sie eine MySQL-Funktion aufrufen, bevor der Thread
mysql_init()
oder
mysql_connect()
aufgerufen hat, wurden die
Thread-spezifischen Variablen für den Thread noch nicht
angelegt und Sie riskieren, dass es früher oder später zu
einem Core Dump kommt.
Damit alles reibunbslos funktioniert, müssen Sie Folgendes tun:
Rufen Sie my_init()
am Anfang Ihres
Programms auf, wenn dieses vor
mysql_real_connect()
noch eine andere
MySQL-Funktion aufruft.
Rufen Sie im Thread-Handler
mysql_thread_init()
auf, ehe Sie
irgendeine MySQL-Funktion benutzen.
Im Thread müssen Sie mysql_thread_end()
vor pthread_exit()
aufrufen. Das gibt den
Speicher frei, den MySQL für Thread-spezifische Variablen
reserviert hat.
Eventuell werden Fehler aufgrund von undefinierten Symbolen
gemeldet, wenn Sie Ihren Client mit
libmysqlclient_r
verlinken. In den meisten
Fällen liegt dies daran, dass Sie vergessen haben, auf der
Link/compile-Zeile die Thread-Bibliotheken einzubinden.
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.