クライアントライブラリはほぼスレッドセーフです。最大の問題は、net.c
で記述されているソケットからデータを読み込むためのサブルーチンが、割り込みが発生したときにスレッドセーフではないことです。これは、サーバに対する読み込みに長時間かかる場合、それを中断できるアラームをユーザが独自に作成する可能性があるという考えに基づく仕様です。割り込み
SIGPIPE
に対する割り込みハンドラをインストールする場合は、ソケットの処理をスレッドセーフにする必要があります。
バージョン 4.0.16 の新機能:
接続が切断されたときにプログラムが強制終了しないようにするために、MySQL
は最初に
mysql_server_init
()、mysql_init()
、または
mysql_connect()
を呼び出すときに
SIGPIPE
をブロックします。独自に
SIGPIPE
に対する割り込みハンドラを作成する場合、まず
mysql_server_init()
を呼び出してから、そのハンドラをインストールする必要があります。MySQL
の古いバージョンでは、スレッドセーフなクライアントライブラリでのみ、mysql_init()
を呼び出すたびに、SIGPIPE
がブロックされていました。
当社の Web サイト(http://www.mysql.com/)で配布した古いバイナリファイルの場合、クライアントライブラリのコンパイルではスレッドセーフなオプションを使用しないのが普通でした(Windows のバイナリはデフォルトでスレッドセーフでコンパイルされます)。新しく配布するバイナリでは、スレッドセーフなクライアントライブラリとそうでないクライアントライブラリの両方が必要です。
別のスレッドから割り込んだり、MySQL
サーバとの通信にタイムアウトを設定できるようなスレッドクライアントを作成するには、-lmysys
、-lmystrings
、および
-ldbug
の各ライブラリ、およびサーバが使用する
net_serv.o
コードを使用する必要があります。
割り込みやタイムアウトを使用しない場合は、スレッドセーフなクライアントライブラリ
(mysqlclient_r)
をコンパイルして使用するだけで済みます。See
項11.1. 「MySQL C API」。
この場合、net_serv.o
オブジェクトファイルや他の MySQL
ライブラリを使用する必要はありません。
スレッドクライアントを使用しながら、タイムアウトや割り込みも使用する場合、thr_alarm.c
ファイルで定義されているルーチンを活用できます。mysys
ライブラリのルーチンを使用している場合、まず
my_init()
を呼び出す必要があります。 See
項11.1.10. 「C API スレッド関数の説明」。
mysql_real_connect()
以外のすべての関数は、デフォルトでスレッドセーフです。以下に、スレッドセーフなクライアントライブラリをコンパイルし、スレッドセーフに使用する方法を示します(mysql_real_connect()
を使用した以下の記述は
mysql_connect()
にも同様に適用できますが、mysql_connect()
は廃止されたので、いずれにしろ
mysql_real_connect()
を使用する必要があります)。
mysql_real_connect()
をスレッドセーフにするには、以下のコマンドを使用してクライアントライブラリを再コンパイルする必要があります。
shell> ./configure --enable-thread-safe-client
このコマンドによって、スレッドセーフなクライアントライブラリ
libmysqlclient_r
が作成されます(使用する OS
にスレッドセーフな gethostbyname_r()
関数が提供されていると仮定)。このライブラリは接続ごとにスレッドセーフになります。以下の項目に注意すれば、2
つのスレッドで同じ接続を共有できます。
2 つのスレッドが同じ接続で同時に MySQL
サーバにクエリを送信することはできない。特に、mysql_query()
を呼び出してから
mysql_store_result()
を呼び出すまでの間は、他のスレッドが同じ接続を決して使用しないようにする必要がある。
複数のスレッドが
mysql_store_result()
で取得した複数の結果セットにアクセスすることができる。
mysql_use_result
を使用する場合、結果セットをクローズするまで、同じ接続を他のスレッドが使用しないようにする必要がある。ただし、最も望ましいのは、同じ接続を共有するスレッドクライアントが
mysql_store_result()
を使用することである。
同じ接続で複数のスレッドを使用する場合、mysql_query()
を呼び出す前から
mysql_store_result()
を呼び出した後までの部分を mutex
ロックで囲む必要がある。mysql_store_result()
が復帰した後はロックを解放することができ、同じ接続で他のスレッドがクエリを実行できるようになる。
POSIX
スレッドを使用してプログラムする場合、pthread_mutex_lock()
および pthread_mutex_unlock()
を使用して、mutex
ロックを設定および解放できる。
MySQL データベースに接続しない MySQL 関数を呼び出すスレッドを使用する場合、以下の事項を認識しておく必要があります。
mysql_init()
または
mysql_connect()
を呼び出すと、MySQL
はスレッドごとにスレッド固有の変数を作成します。この変数は特にデバッグライブラリで使用されます。
スレッドが mysql_init()
または
mysql_connect()
を呼び出す前に MySQL
関数を呼び出すと、スレッドは必要なスレッド固有の変数を設定せず、そのうちコアダンプが発生します。
処理を円滑に進めるには、以下に示す項目を実行する必要があります。
mysql_real_connect()
を呼び出す前に他の MySQL
関数を呼び出す場合、プログラムの先頭で
my_init()
を呼び出す。
MySQL 関数を呼び出す前にスレッドハンドラで
mysql_thread_init()
を呼び出す。
スレッドでは、pthread_exit()
を呼び出す前に mysql_thread_end()
を呼び出す。これにより MySQL
が作成したスレッド固有の変数が使用していたメモリが解放される。
クライアントを libmysqlclient_r
とリンクするときに、未定義シンボルがあるというエラーが発生する可能性があります。ほとんどの場合、これはリンク/コンパイル行にスレッドライブラリを追加しなかったことが原因です。
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.