クライアントライブラリはほとんどスレッドセーフです。最大の問題は、ソケットから読み取られる net.c
内のサブルーチンが割り込みセーフ (interrupt-safe) でないことです。これは、サーバーへの長い読み取りを中断できる独自のアラームを必要とする可能性があるという考えで行われました。SIGPIPE
割り込みの割り込みハンドラをインストールする場合、ソケット処理はスレッドセーフであるべきです。
接続の終了時のプログラムの中止を避けるため、MySQL は、mysql_library_init()
、mysql_init()
、または mysql_connect()
への最初の呼び出しで SIGPIPE
をブロックします。独自の SIGPIPE
ハンドラを使用するには、まず mysql_library_init()
を呼び出してから、ハンドラをインストールします。
libmysqlclient
クライアントライブラリに対するリンク時に、「未定義のシンボル」エラーが発生した場合、多くの場合、これはリンク/コンパイルコマンドでスレッドライブラリを含めていなかったためです。
クライアントライブラリは接続ごとにスレッドセーフです。2 つのスレッドに、同じ接続を共有させることができますが、次の警告を伴います。
-
複数のスレッドは同じ接続で同時に MySQL サーバーにクエリーを送信できません。特に、1 つのスレッドでの
mysql_query()
とmysql_store_result()
の呼び出しの間に、ほかのスレッドが同じ接続を使用しないことを確認する必要があります。mysql_query()
およびmysql_store_result()
呼び出しのペアを相互排他ロックで囲む必要があります。mysql_store_result()
が戻ったら、ロックを解除でき、ほかのスレッドが同じ接続をクエリーできます。POSIX スレッドを使用する場合、
pthread_mutex_lock()
およびpthread_mutex_unlock()
を使用して、相互排他ロックを確立し、解除できます。 多くのスレッドは、
mysql_store_result()
によって取得されるさまざまな結果セットにアクセスできます。mysql_use_result()
を使用するには、結果セットが閉じられるまで、同じ接続を使用しているほかのスレッドがないことを確認する必要があります。ただし、同じ接続を共有するスレッドクライアントがmysql_store_result()
を使用することが実際にもっとも適切です。
MySQL データベースへの接続を作成していないが、MySQL 関数を呼び出しているスレッドがある場合、次のことを知る必要があります。
mysql_init()
を呼び出すと、MySQL は、特にデバッグライブラリによって使用されるスレッドのスレッド固有の変数を作成します。スレッドが mysql_init()
を呼び出す前に、MySQL 関数を呼び出した場合、そのスレッドには必要なスレッド固有変数が設定されていないため、遅かれ早かれコアダンプが生成される可能性があります。問題を回避するには、次を実行する必要があります。
ほかのすべての MySQL 関数の前に
mysql_library_init()
を呼び出します。それはスレッドセーフでないため、スレッドが作成される前にそれを呼び出すか、相互排他ロックで呼び出しを保護します。mysql_thread_init()
が、スレッドハンドラ内の MySQL 関数を呼び出す前の早期に呼び出されるように調整します。mysql_init()
を呼び出すと、それが自動的にmysql_thread_init()
を呼び出します。スレッド内で、
pthread_exit()
を呼び出す前にmysql_thread_end()
を呼び出します。これにより、MySQL スレッド固有変数によって使われたメモリーを解放します。
mysql_init()
に関する先述の注記は、mysql_init()
を呼び出す mysql_connect()
にも適用します。