ラベル Postgres の投稿を表示しています。 すべての投稿を表示
ラベル Postgres の投稿を表示しています。 すべての投稿を表示

2017年7月25日火曜日

Postgresで現在の接続数を確認する

■現在、接続されているConnectionを確認するには
「pg_stat_activity」というテーブルを確認するとよい。

  SELECT * FROM pg_stat_activity


ここに登録されているレコード1件ずつが現在接続されているConnectionである。
レコードが100件あったら、現在接続されているConnection数は、100ということになる。


■実行中のトランザクションを確認するには
上記「pg_stat_activity」テーブルの「xact_start」列が入っている場合は、そのコネクションでトランザクションが実行されている状態。



もし、実行プログラムが終了しているのに、この列に値が入っているような場合は、コミット漏れのトランザクションがある可能性があるので注意が必要。
特に、コミット漏れが原因で、他のトランザクションのレスポンスが著しく遅くなる場合があるのでコミット漏れがないかは、確実にチェックしておいたほうがいいと思われる。
 ちなみに、上記のQuery列に「SHOW TRANSACTION ISOLATION LEVEL」で表示されるのは、コネクションプールを使って接続した場合のコネクションであることが多い。


■強制的に、コネクションを切断するには
 以下のコマンドを実行すればよい。

SELECT pg_terminate_backend(PID)

※PIDは、上記「pg_stat_activity」テーブルの「pid」列値を使うとよい。
※ただし、コネクションプールなどで保持されているコネクションを強制的に切断した場合は
 再度、コネクションプールのコネクションでプログラムが実行された場合、当然のことながらエラーになるので注意が必要。 (このコマンドの使用は開発中の作業に限定されると思われる)


2017年1月11日水曜日

Postgresチューニングパラメータ(主なもの)

Postgresのチューニングパラメータの備忘録。(9.3ベースの設定ファイル)
postgres.confで設定される。
多くのPostgresのチューニングパラメータは、一昔前のPCを意識したような設定値であり、
最近のPCスペックにあった設定をしておいたほうがいい。


■メモリ関連
☆shared_buffers = 2048MB            # min 128kB
                    # (change requires restart)
    表領域をキャッシュする領域。
    たとえば、SELECTを実行するときに、この領域にデータがあれば
    ディスクアクセスせずここのデータを読み書きする。
    ディスクアクセス回数を減らすことができれば、処理が速くなる。
   
    OSキャッシュとの兼ね合いもあるので、あまり大きくすることは推奨されない。
    実メモリの25%がいいといわれている。
   
    また、指定方法は古いバージョンではバッファ指定だったが、
    最近のバージョンでは、バッファ指定できないようだ。
    GB、MB、kBの単位で設定するようにする。


☆work_mem = 1MB                # min 64kB
 Postgresが処理に使うワーキングメモリ。
 (実メモリ-shared_buffers)/max_connectionsを超えるとスワップするので注意。
 

☆maintenance_work_mem = 16MB        # min 1MB
 バキュームなどのメンテナンス処理に使われるワーキングメモリ。
 少なすぎると、バキュームされないことがあるという人もいるが詳細不明。



■コネクション関連
☆max_connections = 300
 work_memとの関係に注意。
 work_memは接続ごとに発生するので、work_mem*max_connectionsのメモリを確保しておかないと、スワップ発生の危険性がある。
 (実メモリ-shared_buffers)/max_connectionsを超えるとだめ。

☆tcp_keepalives_idle = 60        # TCP_KEEPIDLE, in seconds;
                    # 0 selects the system default
 コネクションを完全に接続するまでの待ち時間。
 デフォルトが大きいので、確実な値を設定しておくのがベター。
                   
tcp_keepalives_interval = 5        # TCP_KEEPINTVL, in seconds;
                    # 0 selects the system default


■BackGround Writer
 BackGround Writerは、CheckPointが発生するまでに、
 ディスク書き込みを少しでもしておくことで負荷の分散を計るもの。
 負荷の分散が目的であり、処理量を減らすものではない。
 
 アプリケーションで画面を表示するなどの場合、極端に遅いタイミングがあっては困るが
 チェックポイントの書き込み量が多いときには、処理が極端に遅くなる可能性がある。
 そういった場合に、BackGroundWriterによって、チェックポイントの書き込みが減るように
 少しずつ書き込みをおこない、チェックポイント処理を軽減して、極端な処理落ちを防ぐことができる。(処理を分散するだけで、処理量を減らすものではない。)
 
 逆に、大量データ処理の場合などは、負荷の分散よりも最終処理時間が大事なので、
 チェックポイントに任せておいても問題ないと思われる。
 (1回にたくさん書き込みしたほうがディスクアクセスを減らせるため)
 その場合、チェックポイントとバキュームの発生タイミングなどのチューニングがむしろ重要だと考えられる。
 
 
☆bgwriter_delay = 5000ms            # 10-10000ms between rounds
 BackGroundWriterの実行間隔。

☆bgwriter_lru_maxpages = 1000        # 0-1000 max buffers written/round
 BackGroundWriterが書込むサイズの最大値。
 1バッファは8KB。
 0にすると、BackGroundWriterを発生させない。

☆bgwriter_lru_multiplier = 10.0        # 0-10.0 multipler on buffers scanned/round
 最近の周期で書き込んだ平均とこの値が掛け合わされて、BackGroundWriterが書込むサイズの最大値とする。なお、ここで算出した最大値とbgwriter_lru_maxpagesの小さいほうが採用される。


■WAL
☆wal_buffers = 64MB            # min 32kB, -1 sets based on shared_buffers
                    # (change requires restart)
    WAL=いわゆるトランザクションログをバッファリングしておく領域。
    基本的には、コミットのときに、WALログファイルに書き込まれる。
    その他、WALバッファがあふれたとき、Checkpoint、Vacuum実行時、WALライター実行時などにWALログファイルに書き込まれる。

 多くの更新を実行するトランザクションがある場合は、WAL_Buffersは大きい目に設定しておいたほうが
 ディスク書き込みを減らすことができる。

 デフォルトの-1で、SharedBufferの1/32を割り当てる。
 ただし、64KBから16MBの範囲内であり、それより大きい値を設定する場合は変えたほうがいい。
 8.1まではバッファ指定だが、それ以降は、サイズ指定する。


☆wal_writer_delay = 200ms        # 1-10000 milliseconds
 WAL Writerの実行周期。

2016年12月10日土曜日

オートバキュームがされない原因は? (Postgres)

 Postgresは、MVCC(多版式同時実行制御)の追記型なので、新規行作成(INSERT)だけでなく、
更新(UPDATE)の場合も内部では行データ(タプルという)が新たに増えていきます。
そのため、UPDATEを繰り返すだけでも、データがどんどん増えていき、
パフォーマンスが極端に落ちてしまうことがあります。

これを解決するために、Postgresでは、不要な行データを削除すること(バキュームという)が
必要となってきます。

昔は、バキュームコマンドを定期的に実行する必要がありましたが、
最近のPostgresでは、オートバキューム機能があるため、特に気にすることもなく、
勝手にバキュームしてくれます。

と、思っていましたが・・・
どういうわけか、担当プロジェクトの大量データ処理で激しい処理落ちが・・・

そして、原因調査へ


■まずは、バキューム関係のパラメータを設定
バキュームログを出力して、状況の詳細を確認する。

Postgres.confで、バキュームログを出力するように設定
autovacuum = on
log_autovacuum_min_duration = 0

※postgresの再起動が必要
※postgres.confは、デフォルトなら「C:\Program Files\PostgreSQL\9.x\data」にあるはず。

■ログの確認
そして、再実行して、処理落ちがはじまったところでログを見てみると



やはり、タプルが残っていて、バキュームされていないように見える。
※このテーブル「ad_sequence」の実際の行は1479行であり、それに対してタプルが多すぎる。
※Postgresのログは、デフォルトなら「C:\Program Files\PostgreSQL\9.x\data\pg_log」に
日時付ファイル名で出力されている。


■さらに、PGAdminで、タプル状態の確認



これを見ても、やはり、タプルが残っているようだ。


■いろいろググッてみると、
Let's Postgresの以下のサイトを見つけた。
HOT(Heap Only Tuples) ~ Let's Postgres

HOT(Heap Only Tuple)といわれる機能があって、バキューム処理をしてくれるらしいのだが・・・

だけど、処理が激落ちしているので、それすら走っていない気がする。

そして、さらに上記サイトを読み進めていくと
ロングトランザクションに気をつけようということにひっかかる。


■ロングトランザクションとコネクションプールに注意!!!
  改めて、ソースを確認していくとなんとコミット漏れがあり
それをコミットすることで状況は無事解決した。
(めでたし、めでたし、苦労のわりには、原因はイージーミスという情けない幕切れ。)

実行中のトランザクションで、更新されたテーブルは
そのトランザクションが終了するまでバキュームされないようだ。

ここでもうひとつ注意が必要なのは、コネクションプールについてである。
コネクションプールを使っていると、トランザクションがコミットされていても
バキュームされないことがあるようだ。

詳細不明だが、コネクションプールの機能は、プログラムからコネクションをクローズしても
物理的なコネクションはクローズされず、ある程度の期間(KeepAlive)、
コネクションを保持したり、使いまわしをするもののため、
そのKeepAliveの間は解放されないのではないかと推測しています。

なので、大量データ処理では、コネクションプールを使わず、コネクションの時間的コストはかかるが、適度なタイミングで、コネクションを解放して、再接続をしたほうがいいという結論に至りました。