データベースにまつわる恐い話?

http://itpro.nikkeibp.co.jp/article/COLUMN/20070320/265660/
恐いかな? PostgreSQLのvacuumの話は恐いけど。

      • -

ところで、DBMSを使った開発でのトラブルで、ありがちで、しかもプログラマやテスタに知識がないとレビューやテストを簡単にすり抜けてしまうという意味で恐いものとして、スレッド間でのコネクションの共有を思い出します。
そもそも、マルチスレッドプログラミングでDBコネクションをスレッド間で共有してはいけないということそのものを知らないという人が結構いて、そういう人はDB接続のオーバーヘッドを嫌って(なぜかそういう知識だけはある)、static変数にコネクションを持たせて、スレッド間で共有するような、くらくらくるようなプログラムを書いたりします。
そこまでひどい事はなくても、自前でコネクションプールを作っていて、コネクションを使い終わってプールに戻すときに、プールに同じコネクションがすでに登録されていないことを確認しないでプールに戻してしまうので、プールにコネクションが二重に登録されて、後でタイミングによって同時に二重に登録されたコネクションが取り出されて、結果的にスレッド間でコネクションが共有されることがあります。
マルチスレッドに関するバグは、後工程になるほどチェックすることが難しくなるので、まずデザインの段階でスレッドの競合が起こらない構成にして、コードレビューの段階で危険な部分の入念なチェックとそうでない部分の簡単な規約違反のチェックとを行って、テストに頼らないでバグを回避できるようにしなければならないというのが、私の今のところの見解なのですが、
コードレビューしないとか、コードレビューしても知識がないので気づかないという理由で、危険な状態になっているというのをいくつか見たことがあります。
問題があることに気づいてはいるのだけれど、DBコネクションをスレッド間で共有してはいけない理由をきちんと理解していないせいで、コネクションをオープンするところだけや、ステートメントを実行するところだけをsynchronizedにしているというのもあります。
そもそもsynchronizedにしてスレッドの問題を回避するのは、並列実行性を損なっているのであまり意味がないと思うのですが、もしsynchronizedするならば、トランザクションを開始したところからcommitないしrollbackするところまで囲っておかないと、途中で別のスレッドに処理が割り込まれてcommitしたくないタイミングでcommitがかかったり、場合によってはDBとの通信が混信して想定外のSQLエラーが発生したりします。
こういうところは分かっている人からみれば、絶対そういうことはしそうもないのですが、現実には結構あって、潜在的なバグとして眠っていたりします。