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

17

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

在主节点上:

postgresql.conf 的数据库复制配置如下(为简洁起见,已省略了注释行):

max_wal_senders = 1            
wal_keep_segments = 8          

在从属节点上:

postgresql.conf 与主节点相同。 recovery.conf 如下所示:

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

最初设置时,我们进行了一些简单的测试,并确认了复制正在工作。然而,在进行初始数据加载时,只有部分数据传输到从服务器。

从服务器的日志现在充满了像这样的消息:

< 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 频道上进行了一些分析和帮助后,我得出结论是从库无法跟上主库的速度。 我提出的解决方案如下:

在主库上:

  1. 设置 max_wal_senders=5
  2. 设置 wal_keep_segments=4000。是的,我知道这很高,但我想监控情况并观察会发生什么。我在主库上有空间。

在从库上:

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

我漏掉了什么吗?有没有更好的方法使从库保持最新状态而不必重新加载所有数据?

非常感谢任何帮助。


1
你已经回答了自己的问题 - 将wal_keep_segments设置得足够高,以便在一次wal更新爆发后,从服务器能够追赶上来。 - Ben Grimm
重新创建从属节点怎么样?我的建议流程是否有效? - Oleg Dulin
5个回答

30

处理WAL的两个重要选项适用于流式复制:

  • 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"'
当从主服务器无法直接获取WAL段时,从服务器将尝试使用restore_command加载它。您可以使用archive_cleanup_command设置来配置从服务器自动删除WAL段。
如果从服务器遇到下一个需要的WAL段在主服务器和归档中都不存在的情况,则没有办法恢复数据库的一致性。那么唯一合理的选择是擦除服务器并从新的pg_basebackup开始。

2

1
如果设置 keep_wal_segments 过低,您将会得到该错误。在设置 keep_wal_segments 的值时要考虑 “pg_basebackup 需要多长时间?”的因素。
请记住每5分钟会生成一个新的 WAL 日志段,所以如果备份需要1小时,则至少需要保存12个 WAL 日志段。如果备份需要2小时,则需要24个 WAL 日志段,以此类推。我建议将该值设置为备份每小时需要保存 12.2 个 WAL 日志段。

1

实际上,要进行恢复,您不必删除整个数据库并从头开始。由于主服务器具有最新的二进制文件,因此您可以执行以下操作来恢复从服务器并使它们重新同步:

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. 从服务器必须通过service stop关闭
2. 主服务器将因查询pg_start_backup而转为只读状态
3. 主服务器可以继续提供只读查询服务
4. 在步骤结束时恢复从服务器
我在生产环境中执行了此操作,效果非常好。从服务器和主服务器同步,没有数据丢失。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接