如何修复无法跟上主服务器的 PostgreSQL 9.3 从服务器?

How do I fix a PostgreSQL 9.3 Slave that Cannot Keep Up with the Master?

我们有一个主从复制配置如下。

关于高手:

postgresql.conf 复制配置如下(为简洁起见删除了注释行):

max_wal_senders = 1            
wal_keep_segments = 8          

从机上:

与 master 相同 postgresql.confrecovery.conf 看起来像这样:

standby_mode = 'on'
primary_conninfo = 'host=master1 port=5432 user=replication password=replication'
trigger_file = '/tmp/postgresql.trigger.5432'

最初设置时,我们执行了一些简单的测试并确认复制工作正常。然而,当我们进行初始数据加载时,只有部分数据到达了从站。

Slave 的日志现在充满了如下所示的消息:

< 2015-01-23 23:59:47.241 EST >LOG:  started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:47.241 EST >FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000000F00000052 has already been removed

< 2015-01-23 23:59:52.259 EST >LOG:  started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:52.260 EST >FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000000F00000052 has already been removed

< 2015-01-23 23:59:57.270 EST >LOG:  started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:57.270 EST >FATAL:  could not receive data from WAL stream: ERROR:  requested WAL segment 000000010000000F00000052 has already been removed

在#postgresql IRC 频道上进行了一些分析和帮助后,我得出的结论是slave 跟不上master。我提出的解决方案如下。

关于高手:

  1. 设置max_wal_senders=5
  2. 设置wal_keep_segments=4000。是的,我知道它非常高,但我想监控情况并看看会发生什么。我在master上有空

从机上:

  1. 将配置文件保存在数据目录中(即pg_hba.conf pg_ident.conf postgresql.conf recovery.conf
  2. 清除数据目录(rm -rf /var/lib/pgsql/9.3/data/*)。这似乎是 pg_basebackup.
  3. 所要求的
  4. 运行命令如下: pg_basebackup -h master -D /var/lib/pgsql/9.3/data --username=replication --password

我错过了什么吗?有没有更好的方法使从站更新 w/o 必须重新加载所有数据?

非常感谢任何帮助。

正如 Ben Grimm 在评论中所建议的那样,这是一个确保将段设置为最大可能值以允许从机赶上的问题。

处理WAL for streaming replication的两个重要选项:

  • wal_keep_segments 应该设置得足够高,以允许从设备在合理的滞后后赶上来(例如,高更新量,从设备离线等)。

  • archive_mode 启用 WAL 归档,可用于恢复早于 wal_keep_segments 提供的文件。从属服务器只需要一种方法来检索 WAL 段。 NFS 是最简单的方法,但是从 scp 到 http 再到磁带的任何方法都可以,只要可以编写脚本。

    # on master
    archive_mode = on
    archive_command = 'cp %p /path_to/archive/%f' 
    
    # on slave
    restore_command = 'cp /path_to/archive/%f "%p"'
    

    当slave不能直接从master拉取WAL段时,它会尝试使用restore_command加载它。您可以使用 archive_cleanup_command 设置将从站配置为自动删除段。

如果从服务器遇到主服务器和存档都缺少它需要的下一个 WAL 段的情况,将无法一致地恢复数据库。 唯一 合理的选择是清理服务器并从新的 pg_basebackup 重新启动。

实际上要恢复,您不必丢弃整个数据库并从头开始。由于 master 有最新的二进制文件,您可以执行以下操作来恢复 slave 并使它们恢复同步:

psql -c "select pg_start_backup('initial_backup');"
rsync -cva --inplace --exclude=*pg_xlog* <data_dir> slave_IP_address:<data_dir>
psql -c "select pg_stop_backup();"

注:
1. slave 必须被 service stop
拒绝 2.master会因为查询pg_start_backup
转为只读 3. master 可以继续提供只读查询
4. 在步骤结束时带回奴隶

我在产品中这样做了,它对我来说很完美。 slave 和 master 是同步的,没有数据丢失。

您可以为 postgress 配置 replication slots 以保留此类插槽中提到的副本的 WAL 段。

https://www.percona.com/blog/2018/11/30/postgresql-streaming-physical-replication-with-slots/

阅读更多内容

在主服务器上 运行

SELECT pg_create_physical_replication_slot('standby_slot'); 

在从属服务器上将下一行添加到 recovery.conf

primary_slot_name = 'standby_slot'

如果 keep_wal_segments 设置太低,您将收到该错误。 当您设置 keep_wal_segments 的值时,请考虑 "How long is the pg_basebackup taking?"

请记住,分段大约每 5 分钟生成一次,因此如果备份需要一个小时,您至少需要保存 12 个分段。在 2 小时,您需要 24,等等。我会将值设置为大约 12.2 segments/hour 备份。