postgres中wal日志被覆盖的解决方法

postgres中wal日志被覆盖的解决方法

参考博文:https://blog.csdn.net/prettyshuang/article/details/51777645

在搭建主备流复制环境,并进行pg_bench的压力测试时,备机的日志中会有如下错误:

PostgreSQL:“ FATAL: requested WAL segment00800002A0 has already been removed”

原因是,主机进行了大数据量的操作,导致产生的wal日志过快,由于wal日志的策略,导致之前的wal日志被覆盖掉,此时在进行主备关系同步时,发现wal日志已经被覆盖,无法读取到正确的wal日志信息,进而导致主备关系断开。

目前有如下三种方式可以规避该问题:

一、调整wal_keep_segments的值

将GUC参数wal_keep_segments设大一些,比如设置为2000,而每个segment默认值为16MB,就相当于有32000MB,即大概30多个GB的空间作为缓存空间。

不过,该方法并不能从根本上解决该问题。毕竟,在生产环境中或TPCC等测试灌数时,如果某条事务需要插入几十亿条记录,有可能还是会出现该问题。

二、启用归档

归档,就是将未发送到备库的xlog备份到某个目录下,待重启数据库时再将其恢复到备库中去。

GUC参数设置示例如下:

主库的postgresql.conf文件中:

wal_level = hot_standby
archive_mode = on
archive_command = 'rsync -zaq %p postgres@pg-slave:/var/lib/pgsql/wal_restore/%f && test ! -f /var/lib/pgsql/backup/wal_archive/%f && cp %p /var/lib/pgsql/backup/wal_archive/'
archive_timeout = 300
max_wal_senders = 5
wal_keep_segments = 0 # not sure why I've set it to this?

备库的postgresql.conf文件中:

wal_level = hot_standby
archive_mode = on
archive_command = 'test ! -f /var/lib/pgsql/backup/wal_archive/%f && cp -i %p /var/lib/pgsql/backup/wal_archive/%f < /dev/null'
hot_standby = on
wal_keep_segments = 1

备库的recovery.conf文件中:

standby_mode = 'on'
primary_conninfo = 'host=pg-master port=5432 user=replicator'
restore_command = 'cp /var/lib/psql/wal_restore/%f %p'
archive_cleanup_command = 'pg_archivecleanup /var/lib/pgsql/wal_restore/ %r'

三、启用replication slot (pg9.4以后才有)
这个方法算是根本解决方法,不会造成xlog(wal日志)的丢失。也就是说,在xlog被拷贝之前,不会删除。

启用方法:

(1)在postgresql.conf中添加:

max_replication_slots = 2000

(2)在拷贝到备库之前,主库要创建一个slot:

postgres=# SELECT * FROM pg_create_physical_replication_slot('node_a_slot');
 slot_name  | xlog_position
-------------+---------------
 node_a_slot |

postgres=# SELECT * FROM pg_replication_slots;
  slot_name  | slot_type | datoid | database | active | xmin | restart_lsn
-------------+-----------+--------+----------+--------+------+-------------
 node_a_slot | physical  |        |          | f      |      |
(1 row)

(3)在备库的recovery.conf文件中添加一行:

standby_mode = 'on'
primary_conninfo = 'host=192.168.4.225 port=19000 user=wslu password=xxxx'
primary_slot_name = 'node_a_slot'

你可能感兴趣的:(postgres中wal日志被覆盖的解决方法)