sql - 在 postgres 的 pg_dump 中节流 i/o?

标签 sql postgresql sysadmin database-backups

所以我们在一台 16GB RAM 的机器上有一个 32GB 的生产数据库。由于缓存,这通常根本不是问题。但是每当我启动数据库的 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;

我只看到标记为 granted = '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

最佳答案

  1. 最简单的: 您可以使用 pv 来限制 pg_dump .
  2. 越难: 更改备份过程。使用例如:
        psql -c 'pg_start_backup()'
        rsync --checksum --archive /var/lib/pgsql /backups/pgsql
        psql -c 'pg_stop_backup()'
    
    但请注意,您还需要 continuous archiving为此进行设置,备份期间创建的所有 WAL 文件都存储在数据文件备份中。
  3. 更难: 您可以在额外的廉价磁盘上设置复制数据库(例如使用 log shipping ),而不是备份生产数据库备份副本。即使它会落后于它最终会 catch 的一些交易。但是在开始备份之前检查副本是否是最新的。

关于sql - 在 postgres 的 pg_dump 中节流 i/o?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3866357/

相关文章:

crash - 什么是崩溃循环?

Apache2 无法启动 - Mac OS X - Passenger

SQL Server 查询(更新分组依据?)

mysql - 重写不带with子句的sql

linux - 在 CentOS 5 中使用 Asterisk 进行 IVR 集成

sql - Postgres WHERE 和 SORT BY 优化

postgresql - 错误、系统查询、Postgresql 查询调试的不同日志文件

linux - inotifywait 报告要创建的文件甚至在创建之前就被删除了

mysql - 选择 SQL 中最常见的项目

sql - 在 Oracle 存储过程中记录错误消息