ログ日記

作業ログと日記とメモ

PDOのデッドロックでハマる

http://php.net/pg-connect

同じ connection_string 引数で 2 回 pg_connect() 関数がコールされた場合は、 connect_type に PGSQL_CONNECT_FORCE_NEW を指定していない限り 既存の接続が返されます。

今まではこの動作のおかげで気軽に接続リソースをオープンできた。
でもPDOを使うと同じ接続文字列であってもリソースが複数用意されるみたい。
だからDAOオブジェクトを2個用意すれば2個の接続が開かれる。psで見るとなるほどpostmasterのプロセスが二つ出来ている。
普通は問題にならないが、テーブルの外部参照とトランザクションを同時に使用するとデッドロックに陥る。


参考
[PostgreSQLウォッチ]第20回 PostgreSQL 8.1ベータ・テスト開始,新機能ロールと共有行ロック(3ページ目) | 日経 xTECH(クロステック)


なのでファクトリクラスのstatic変数で、同じdsnで呼び出された場合は同じPDOオブジェクトを返すように修正すると直った。
ただしこれはこれで、PDOStatementなどのオブジェクト破棄を考慮に入れないといけない。
二つのテーブルから平行してデータを取得、などと出来ないのだ。
http://php.net/PDO-query

PDO->query() を次にコールする前に 結果セット内の全てのデータを取得しない場合、そのコールは失敗します。 PDOStatement->closeCursor() をコールし、 次に PDO->query() をコールする前に PDOStatement オブジェクトに関連付けられたリソースを解放してください。


ORMを利用しているとDBを操作している感覚が無いのでつい忘れてしまうから気を付けねば。