PostgreSQLとNpgsqlのコネクションプールの挙動

Npgsqlを用いてPostgreSQLと接続したときのコネクションプールの挙動について検証したものをトピック形式でメモしておく。

バージョン
・PostgreSQL 13
・Npgsql 8.0.1

Npgsqlの接続プールは各プロセス内のメモリで管理される

NpgsqlのコネクションプールはNpgsql名前空間内のstaticなクラスで管理されている。プロセスを複数立ち上げればそれぞれ別々にプールされる。

接続プールは接続文字列ごとに管理される

接続プールは接続文字列ごとに管理され同じ接続文字列の場合にのみ再利用される。またプールされる数も接続文字列ごとにカウントされる。

これは仮に接続先が同じでもパラメータが違うだけで別々となる。

接続プール数、保持時間は接続文字列で指定する

パラメータ名 意味 未指定時
Pooling プール有無 true
MinPoolSize 最小数 1
MaxPoolSize 最大数 100
ConnectionLifeTime 保持時間(秒) 500

接続の再利用時、セッションパラメータはリセットされる

プールされた接続は再利用前に次の文を発行して状態をリセットしている。

  • SET SESSION AUTHORIZATION DEFAULT
  • RESET ALL

不意の停止でサーバ側にセッションが残る場合がある

コネクションプールはプロセスの終了時にすべて切断される。ただしプロセスの強制中断などで解放処理が走らないとサーバ側でセッションが残ってしまう。残ったセッションはサーバの同時接続数の枠を埋めてしまう。

接続がプールされた状態でDBを再起動すると次の利用時にエラーになる

コネクションプールが残った状態でPostgreSQLサーバを停止・再起動してもプールされた接続のインスタンスは破棄されない。そして次にその接続が再利用されるとNpgsqlException (0x80004005)が発生する。

DBのみ再起動すると予期せぬタイミングで接続エラーとなってしてしまう可能性がある。

最大プール数を超えた場合は待機状態になる

MaxPoolSizeを超えてOpenを行ったとき、接続数に空きが出るまで他の処理の終了を待機する。待機する時間は通常の接続タイムアウトと同じで接続文字列(Timeout)で指定できる。

タイムアウトを超えた場合は接続異常となり例外が発生する。

サーバの同時接続数を超えた場合は即エラーとなる

Npgsqlの最大接続プール数ではなく、PostgreSQL側の最大同時接続数を超えた場合は待機することなく接続異常となる。

現在バージョンではPostgreSQL側の同時最大接続数のデフォルトが100、NpgsqlのMaxPoolSizeのデフォルトも100なので、そのまま利用すると一斉に100オーバーのアクセスがあったとき、遅延ではなくエラーとなり注意が必要である。

コメント