postgreSQL-复制槽

1.复制槽简介

流复制正常工作的时候,主服务器不会为落后的备用服务器保留额外的 WAL。在某些情况
下,由于某些原因,从服务器可能会断开连接,从而导致延迟的时间增大,并且当某些未
复制的 WAL 文件被回收,备用机无法恢复,就会收到如下错误:

ERROR: requested WAL segment 000000010000000000000008 has already been 
removed
复制槽(Physical Replication Slot)提供了一种办法确保主库不会删除还未发送到备库的
WAL 日志,即使备库掉线。
通过 Replication Slot 记录的从库状态,PostgreSQL 会保证从库还没有 apply 的日志,
不会从主库的日志目录里面清除。而且,replication slot 的状态信息是持久化保存的,即
便从库断掉或主库重启,这些信息仍然不会丢掉或失效。

 2.创建复制槽

  • 主库创建复制槽
select * from pg_create_physical_replication_slot('slot1'); 
 slot_name | lsn 
-----------+----- 
 slot1 | 
(1 row) 
select * from pg_replication_slots; 
-[ RECORD 1 ]-------+--------- 
slot_name           | slot1 #复制槽名称 
plugin              | #复制槽对应的输出插件名,如果是物理复制槽,这里显示为空 
slot_type           | physical #复制槽类型,有 physical 或 logical 
datoid              | #复制槽对应的数据库 oid,如果物理复制槽,此字段显示为空 
database            | #复制槽对应的数据库名称,如果物理复制槽,此字段显示为空 
temporary           | f #是否为临时复制操,临时槽不会被保存在磁盘上并且会在出错
或会话结束时自动被删除掉。 
active              | f #当前复制槽,如果正在使用显示为 t 
active_pid          | #使用复制槽会话的进程号 
xmin                | #数据库需要保留的最老事务,VACUUM 不能移除被其后续事务
删除的元组。 
catalog_xmin        | #数据库需要保留的影响系统目录的最旧事务。VACUUM 不能
移除被其后续事务删除的目录元组。 
restart_lsn         | #这个复制操被消费的最旧的 lsn 位置,checkpoint 不会删除这
个 lsn 之后的 wal 文件 
confirmed_flush_lsn | #代表逻辑槽的消费者已经确认接收数据到什么位置的地址
(LSN)。 比这个地址更旧的数据已经不再可用。对于物理槽这里是 NULL。
  •  在从库配置参数,然后重启从库
--修改 postgresql.conf,使其连接到主服务器的复制槽 
vi postgresql.conf 
primary_slot_name = 'slot1' 

--重新加载配置文件 
pg_ctl reload 

--如果一切正常,主库上的复制槽的状态应为 active。 
select * from pg_replication_slots; 
-[ RECORD 1 ]-------+---------- 
slot_name | slot1 
plugin    | 
slot_type | physical 
datoid    | 
database  | 
temporary | f 
active    | t 
active_pid   | 16652 
xmin         | 
catalog_xmin | 
restart_lsn  | 0/3003B98 
confirmed_flush_lsn |

  •  查看 restart_lsn 所在的 wal 文件
restart_lsn 表示主库 checkpoint 的时候不会删除这之后的 wal 日志,为备库保留着
postgres=# select pg_walfile_name(restart_lsn) from pg_replication_slots; 
 pg_walfile_name | 000000010000000000000013
  • 模拟:没有复制槽的情况
postgres=# select pg_drop_replication_slot('slot1'); 
 pg_drop_replication_slot 
-------------------------- 
 
(1 row) 
pg_ctl reload 

postgres=# select * from pg_replication_slots; 
 slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | 
xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn 
-----------+--------+-----------+--------+----------+-----------+--------+------------
+------+--------------+-------------+--------------------- 
(0 rows) 
 
--关掉备库: 
pg_ctl stop 

--主库查看复制状态 
postgres=# select client_addr,sync_state from pg_stat_replication;
 client_addr | sync_state 
-------------+------------ 
(0 rows) 

 
--主库上频繁创建表,以及切换 WAL 日志 
postgres=# create table t2(id int); 
CREATE TABLE 
postgres=# select pg_switch_wal(); 
 pg_switch_wal 
--------------- 
 0/3016168 
(1 row)

postgres=# create table t3(id int);
CREATE TABLE 
postgres=# select pg_switch_wal(); 
 pg_switch_wal 
--------------- 
 0/4003A50

postgres=# create table t4(id int); 
CREATE TABLE 
postgres=# select pg_switch_wal(); 
 pg_switch_wal 
--------------- 
 0/50011A0 
(1 row) 
postgres=# checkpoint;
CHECKPOINT


  • 再启动备库,可以看到流复制关系断了
--备库启动 
pg_ctl start 

--主库查看复制状态 
postgres=# select client_addr,sync_state from pg_stat_replication ; 
 client_addr | sync_state 
-------------+------------ 
(0 rows) 

--查看备库日志 
2023-05-07 10:20:59.162 CST [2079] STATEMENT: START_REPLICATION 
3/61000000 TIMELINE 3 
2023-05-07 10:21:04.167 CST [2080] ERROR: requested WAL segment 
000000030000000300000061 has already been removed
  • 恢复流复制环境,使用复制槽
postgres=# select client_addr,sync_state from pg_stat_replication ; 
 client_addr | sync_state 
-----------------+------------ 
 192.168.1.103 | async 
(1 row) 

postgres=# select * from pg_replication_slots ; 
 slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | 
xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn 
-----------+--------+-----------+--------+----------+-----------+--------+------------
+------+--------------+-------------+--------------------- 
 slot1 | | physical | | | f | t | 4496 | 486 | | 
0/3000060 | 
(1 row) 

 
--同样的操作,关掉备库 
pg_ctl stop 

--主库查看复制状态 
postgres=# select client_addr,sync_state from pg_stat_replication ; 
 client_addr | sync_state 
-------------+------------ 
(0 rows)

--然后主库上频繁的创建表,以及切换 WAL 日志 
postgres=# create table t6(id int); 
CREATE TABLE 
postgres=# select pg_switch_wal(); 
 pg_switch_wal 
--------------- 
 0/3014FF0 
(1 row) 
 
postgres=# create table t7(id int); 
CREATE TABLE 
postgres=# select pg_switch_wal(); 
 pg_switch_wal 
--------------- 
 0/40011A0 
(1 row) 
postgres=# create table t8(id int); 
CREATE TABLE 
postgres=# select pg_switch_wal(); 
 pg_switch_wal 
--------------- 
 0/5003A50 
(1 row) 
postgres=# create table t8(id int); 
CREATE TABLE 
postgres=# select pg_switch_wal(); 
 pg_switch_wal 
--------------- 
 0/5003A50 
(1 row) 
postgres=# create table t10(id int); 
CREATE TABLE 
postgres=# select pg_switch_wal(); 
 pg_switch_wal 
--------------- 
 0/5003A50 
(1 row) 
postgres=# checkpoint ; 

CHECKPOINT 
--启动备库 
pg_ctl start 
--主库查看复制状态 
postgres=# select client_addr,sync_state from pg_stat_replication ; 
 client_addr | sync_state 
-----------------+------------ 
 192.168.1.103 | async 
(1 row)
  • 在备库上查一下是否有这些表,可以看到,流复制正常
postgres=# \d 
 List of relations 
 Schema | Name | Type | Owner 
--------+------+-------+---------- 
 public | t1 | table | postgres 
 public | t10 | table | postgres 
 public | t2 | table | postgres 
 public | t3 | table | postgres 
 public | t4 | table | postgres 
 public | t5 | table | postgres 
 public | t6 | table | postgres 
 public | t7 | table | postgres 
 public | t8 | table | postgres 
 public | t9 | table | postgres 
(10 rows)
总结
复制槽防止备库需要的 wal 日志在主库被删除,主库会根据备库返回的信息确认哪些 wal
日志已不再需要,才能进行清理。
注意
如果收不到从库的 reply,复制槽的状态 restart lsn 会保持不变,造成主库会一直保留本
地日志,可能导致日志磁盘满。所以应该实时监控 wal 日志磁盘使用情况,并设置较小的
wal_sender_timeout,默认为 60s,及早发现从库断掉的情况。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Active-Active复制是指两个或多个PostgreSQL数据库实例之间的多向同步。在这种复制方式中,每个数据库实例都可以读取和写入数据,而不是像传统的主从复制方式那样只允许主节点写入数据,从节点只允许读取数据。 下面是使用docker-compose容器来实现PostgreSQL Active-Active复制的详细步骤: 1. 创建docker-compose.yml文件并定义两个PostgreSQL容器,如下所示: ``` version: '3' services: postgresql1: image: postgres environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: mydb PGDATA: /var/lib/postgresql/data/pgdata volumes: - pgdata1:/var/lib/postgresql/data ports: - "5431:5432" networks: - postgresql postgresql2: image: postgres environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: mydb PGDATA: /var/lib/postgresql/data/pgdata volumes: - pgdata2:/var/lib/postgresql/data ports: - "5432:5432" networks: - postgresql volumes: pgdata1: pgdata2: networks: postgresql: ``` 2. 启动docker-compose容器,运行以下命令: ``` docker-compose up -d ``` 3. 进入postgresql1容器,创建复制用户并授权: ``` docker exec -it postgresql1 bash su postgres psql CREATE USER replication WITH REPLICATION ENCRYPTED PASSWORD 'password'; GRANT ALL PRIVILEGES ON DATABASE mydb TO replication; ``` 4. 修改postgresql.conf文件和pg_hba.conf文件 在postgresql1容器的 /var/lib/postgresql/data 目录下找到postgresql.conf文件和pg_hba.conf文件,修改如下: postgresql.conf: ``` listen_addresses = '*' wal_level = replica max_wal_senders = 10 wal_keep_segments = 32 ``` pg_hba.conf: ``` host replication replication 172.20.0.0/16 md5 ``` 5. 重启postgresql1容器 ``` docker-compose restart postgresql1 ``` 6. 在postgresql2容器中创建复制并启动复制流 ``` docker exec -it postgresql2 bash su postgres psql SELECT * FROM pg_create_physical_replication_slot('replication_slot_name'); pg_basebackup -h postgresql1 -D /var/lib/postgresql/data -U replication -v -P --xlog-method=stream pg_ctl -D /var/lib/postgresql/data start ``` 7. 测试Active-Active复制 在任何一个容器中创建表或插入数据,可以在另一个容器中看到相同的数据。如果其中一个容器出现故障,另一个容器可以继续提供服务,因为它们都具有相同的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值