PgpoolでのPreparedStatementのDEALLOCATE問題
Pgpool(ver 2.3.3)を使っていて、たまにDEALLOCATE*1に関するエラーが発生するので調査していました。
状況
- Pgpoolログに、「DEALLOCATE pdo_stmt_00000001 message: prepared statement "pdo_stmt_00000001" does not exist」とエラー出力される
- PostgreSQLログに、「ERROR: prepared statement "pdo_stmt_00000001" does not exist」とエラー出力される
- このエラーが検知されるのは、全てスレーブノード
原因
以下、引用にもある通り、Pgpoolを「マスター/スレーブモード」で利用している場合、PreparedStatementがマスターノードで作成されたにも関わらず、DEALLOCATE処理をスレーブにも実行していることが原因だろうということです。
Some notices: First we issue a prepared SELECT NEXTVAL in a transaction.
http://pgfoundry.org/pipermail/pgpool-hackers/2010-May/000311.html
This is only send to the master. Later we try to deallocate the prepared
statement. This works on the master, but fails on the slaves. Seems to
be a logic flaw.
少し詳しく書くと、以下のようになります。
- 更新系SQL、または、トランザクション中のSELECTは、(Pgpoolの機能によって)マスタノードで実行される。
- そのSQLがPreparedStatementを用いている場合、PreparedStatementもマスタノードで作成される。
- にも関わらず、DEALLOCATE処理は、マスタ、そしてスレーブにも実行されてしまう。
- そのため、スレーブ側で存在しないPreparedStatement(SQLの雛形)の削除(メモリの解放)に失敗する。
下記の通りこの件は、ver2.3.2で修正されている*2ようなのですが、2.3.3では発生してしまいます。。
2.3.2 (tomiteboshi) 2010/02/07
http://pgpool.projects.postgresql.org/pgpool-II/doc/pgpool-ja.html
バグ修正
master/slaveモードの際に、DEALLOCATEをすべてのノードに送らないようにして、kind mismatchエラーを防ぐようにしました(Tatsuo)
影響
このエラーについて、有識者に確認したところ、
- PDOなどの接続ライブラリが、名前付きのPreparedStatementを作成して、それを明示的に DEALLOCATE するタイプの場合に発生する。
- このエラーが発生したからと言って、データ不整合が発生しているというわけではない。
- また、このエラーによって、データ不整合が発生してしまうこともない。
- この不具合は、Pgpool3.0 で修正されている。
対策
- (できれば使いたいが)PreparedStatementを使用しない
- (実害は無いようなので)サーバ監視でこのエラーを無視
- Pgpool3.0以上にバージョンアップ(または2.3.2にダウン)