在postgres的pg_dump中限制I / O?

use*_*424 5 sql sysadmin postgresql database-backups

因此,我们在具有16GB RAM的计算机上拥有32GB的生产数据库。多亏了缓存,这通常根本不是问题。但是,每当我启动数据库的pg_dump时,来自应用服务器的查询就会开始排队,几分钟后,队列就消失了,我们的应用陷入停顿。

我将第一个承认我们存在查询性能问题,并且正在解决这些问题。同时,我希望能够每晚运行pg_dump,这种方式可以从数据库中吸取信息,并且不会降低应用程序的性能。我不在乎是否要花几个小时。我们的应用程序未运行任何DDL,因此我不必担心锁争用。

为了解决这个问题,我正在使用niceice和ionice来运行pg_dump。不幸的是,这不能解决问题。

nice ionice -c2 -n7 pg_dump -Fc production_db -f production_db.sql
Run Code Online (Sandbox Code Playgroud)

即使有了ionice,我仍然看到上面的问题。似乎I / O等待,并且大量搜寻导致了该问题。

vmstat 1 
Run Code Online (Sandbox Code Playgroud)

向我显示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;
Run Code Online (Sandbox Code Playgroud)

我只看到标记为已授予='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
Run Code Online (Sandbox Code Playgroud)

Tom*_*zky 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. 更难的是:您可以在额外的廉价磁盘上设置复制数据库(例如使用日志传送),而不是备份生产数据库备份副本。即使它会落后于一些交易,它最终也会赶上。但在开始备份之前请检查副本是否是最新的。