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.
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.

http://pgfoundry.org/pipermail/pgpool-hackers/2010-May/000311.html

少し詳しく書くと、以下のようになります。

  1. 更新系SQL、または、トランザクション中のSELECTは、(Pgpoolの機能によって)マスタノードで実行される。
  2. そのSQLがPreparedStatementを用いている場合、PreparedStatementもマスタノードで作成される。
  3. にも関わらず、DEALLOCATE処理は、マスタ、そしてスレーブにも実行されてしまう。
  4. そのため、スレーブ側で存在しないPreparedStatement(SQLの雛形)の削除(メモリの解放)に失敗する。


下記の通りこの件は、ver2.3.2で修正されている*2ようなのですが、2.3.3では発生してしまいます。。

2.3.2 (tomiteboshi) 2010/02/07
バグ修正
master/slaveモードの際に、DEALLOCATEをすべてのノードに送らないようにして、kind mismatchエラーを防ぐようにしました(Tatsuo)

http://pgpool.projects.postgresql.org/pgpool-II/doc/pgpool-ja.html

影響

このエラーについて、有識者に確認したところ、

  • PDOなどの接続ライブラリが、名前付きのPreparedStatementを作成して、それを明示的に DEALLOCATE するタイプの場合に発生する。
  • このエラーが発生したからと言って、データ不整合が発生しているというわけではない。
  • また、このエラーによって、データ不整合が発生してしまうこともない。
  • この不具合は、Pgpool3.0 で修正されている。

対策

  • (できれば使いたいが)PreparedStatementを使用しない
  • (実害は無いようなので)サーバ監視でこのエラーを無視
  • Pgpool3.0以上にバージョンアップ(または2.3.2にダウン)

*1:「DEALLOCATE=確保したメモリーを解放する」という意味で、ここではPreparedStatement用に確保したメモリの解放するために実行したSQLコマンド(DEALLOCATE)が失敗したということになります。

*2:確かに、Pgpool2.3.2であれば発生しないようでした。