6

したがって、16 GB の RAM を搭載したマシン上に 32 GB の運用データベースがあります。キャッシュのおかげで、これは通常まったく問題になりません。しかし、データベースの pg_dump を開始するたびに、アプリ サーバーからのクエリが待ち行列に入り、数分後には待ち行列がなくなり、アプリが停止します。

クエリのパフォーマンスに問題があることを最初に認め、それらに対処しています。その間、私は毎晩pg_dumpを実行できるようにしたいと考えています. 何時間かかっても構わない。私たちのアプリは DDL を実行しないので、ロックの競合について心配する必要はありません。

問題を解決しようとして、nice と ionice の両方で pg_dump を実行しています。残念ながら、これは問題に対処していません。

nice ionice -c2 -n7 pg_dump -Fc production_db -f production_db.sql

ionice を使用しても、上記の問題が引き続き発生します。I/O 待機と多くのシークが問題を引き起こしているようです。

vmstat 1 

iowait が 20 ~ 25% 前後で推移し、40% に急上昇することもあります。実際の CPU % は 2 ~ 5% の間で変動し、場合によっては 70% に急上昇します。

ロックが原因である可能性はないと思います。このクエリを実行すると:

select pg_class.relname,pg_locks.* from pg_class,pg_locks where pg_class.relfilenode=pg_locks.relation;

grant = 't' とマークされたロックのみが表示されます。通常、本番環境で DDL を実行することはありません。そのため、ロックは問題ではないようです。

WCHAN 列を有効にした ps からの出力を次に示します。

PID WIDE               S TTY          TIME COMMAND
3901 sync_page         D ?        00:00:50 postgres: [local] COPY
3916 -                 S ?        00:00:01 postgres:  SELECT
3918 sync_page         D ?        00:00:07 postgres:  INSERT
3919 semtimedop        S ?        00:00:04 postgres:  SELECT
3922 -                 S ?        00:00:01 postgres:  SELECT
3923 -                 S ?        00:00:01 postgres:  SELECT
3924 -                 S ?        00:00:00 postgres:  SELECT
3927 -                 S ?        00:00:06 postgres:  SELECT
3928 -                 S ?        00:00:06 postgres:  SELECT
3929 -                 S ?        00:00:00 postgres:  SELECT
3930 -                 S ?        00:00:00 postgres:  SELECT
3931 -                 S ?        00:00:00 postgres:  SELECT
3933 -                 S ?        00:00:00 postgres:  SELECT
3934 -                 S ?        00:00:02 postgres:  SELECT
3935 semtimedop        S ?        00:00:13 postgres:  UPDATE waiting
3936 -                 R ?        00:00:12 postgres:  SELECT
3937 -                 S ?        00:00:01 postgres:  SELECT
3938 sync_page         D ?        00:00:07 postgres:  SELECT
3940 -                 S ?        00:00:07 postgres:  SELECT
3943 semtimedop        S ?        00:00:04 postgres:  UPDATE waiting
3944 -                 S ?        00:00:05 postgres:  SELECT
3948 sync_page         D ?        00:00:05 postgres:  SELECT
3950 sync_page         D ?        00:00:03 postgres:  SELECT
3952 sync_page         D ?        00:00:15 postgres:  SELECT
3964 log_wait_commit   D ?        00:00:04 postgres:  COMMIT
3965 -                 S ?        00:00:03 postgres:  SELECT
3966 -                 S ?        00:00:02 postgres:  SELECT
3967 sync_page         D ?        00:00:01 postgres:  SELECT
3970 -                 S ?        00:00:00 postgres:  SELECT
3971 -                 S ?        00:00:01 postgres:  SELECT
3974 sync_page         D ?        00:00:00 postgres:  SELECT
3975 -                 S ?        00:00:00 postgres:  UPDATE
3977 -                 S ?        00:00:00 postgres:  INSERT
3978 semtimedop        S ?        00:00:00 postgres:  UPDATE waiting
3981 semtimedop        S ?        00:00:01 postgres:  SELECT
3982 -                 S ?        00:00:00 postgres:  SELECT
3983 semtimedop        S ?        00:00:02 postgres:  UPDATE waiting
3984 -                 S ?        00:00:04 postgres:  SELECT
3986 sync_buffer       D ?        00:00:00 postgres:  SELECT
3988 -                 R ?        00:00:01 postgres:  SELECT
3989 -                 S ?        00:00:00 postgres:  SELECT
3990 -                 R ?        00:00:00 postgres:  SELECT
3992 -                 R ?        00:00:01 postgres:  SELECT
3993 sync_page         D ?        00:00:01 postgres:  SELECT
3994 sync_page         D ?        00:00:00 postgres:  SELECT
4

2 に答える 2

0

PS出力には「待機中」状態のUPDATEステートメントが複数ありますが、これはまだロックしていると言っています(ロックテストクエリは別として)。そうでなければ、PS出力に「待機中」が表示されないことは間違いありません。このクエリが問題の発生中に何かを示しているかどうかを確認できますか:

SELECT * FROM pg_stat_activity WHERE waiting;

(実行している PostgreSQL のバージョンを教えてくれなかったので、これが機能するかどうかはわかりません。)

そこに何かがある場合 (つまり、waiting = TRUE の場合)、それはロック/トランザクションの問題です。

于 2010-10-05T21:04:36.573 に答える
0
  1. 最も簡単な方法: pvを使用して pg_dump を調整できます。
  2. より困難: バックアップ手順を変更します。たとえば、次のように使用します。
        psql -c 'pg_start_backup()'
        rsync --checksum --archive /var/lib/pgsql /backups/pgsql
        psql -c 'pg_stop_backup()'
    
    ただし、これを機能させるには、継続的なアーカイブを設定し、バックアップ中に作成されたすべての WAL ファイルをデータ ファイルのバックアップに格納する 必要があることに注意してください。
  3. さらに難しい: 複製されたデータベースを (たとえばログ配布を使用して) 追加の安価なディスクにセットアップし、運用データベースのバックアップの代わりにレプリカをバックアップすることができます。一部のトランザクションが遅れても、最終的には追いつくでしょう。ただし、バックアップを開始する前に、レプリカが適切に最新のものであるかどうかを確認してください。
于 2010-10-05T19:29:06.037 に答える