Threadごとにconnectionを管理できるようにしたからだいじょうだと思っていた。たしかにThread二つまでは何ともなかった。それを四つにしたらおかしくなった。
いきなりPREPAREがすでに使われている、とエラーになる。
——?
どうして二つで動いていたものが、四つだと動かなくなる?
しかもすぐに起きることもあれば、しばらくたってから起きることもある。同じ処理をくりかえしているにもかかわらず。
三日、考えこんだ。
使っているライブラリも疑った。
どうデバックすれば、いいかも思いつかない。タイミングで発生しているのはあきらかで——それを補足するのはどうすれば、いいのだろう。ソース百遍。
三日目にしてようやく気づいた。
threadごとに管理しているconnectionはハッシュテーブルを使っている。
同時にこのハッシュテーブルにアクセスされたらどうなるんだろう?
あっ、まずいかもしれない。
ハッシュテーブルがthreadセーフなら別だが——。
どうやれば、それがわかるのか、わからなかったのでとりあえず対処した。
「with-lock-held」で処理を排他1。
それでエラーはいちおう起きなくなったように見えた。が、それは頻度が極端に減っただけで起きるときには起きる。あれ?
これがわからない。謎だ。
同じPREPAREがすでに使われているというエラーなのだが——たぶんthreadセーフじゃないところがまだ、どこかに残っているのだろう。あるいは使っているライブラリかもしれない。むずかしい。
これを避ける方法にはsqlを発行しているところをハッシュテーブルのときのように排他処理をかければ、いいのだが……それだと並列処理の意味がなくなってしまう。
threadひとつだけの場合とかわらないからだ。
まったくthreadで動くようにしたらthreadにした意味自体がなくなってしまう、という……。
なんて厄介な2。