作者
digoal
日期
2019-10-27
标签
PostgreSQL , pg_receivewal , sync replication , mirror , redo , wal , 0丢失 , archive , reltime
背景
wal,redo是数据库的重做日志,事务提交前,务必保证事务产生的修改对应的重做日志都已经持久化,为什么不直接将修改的数据持久化,而是重做日志呢?主要是通常对事务对数据库产生的修改(数据新增、修改或索引数据块的新增和修改)涉及的数据本身是离散的,数据库被设计出来的时候,存储数据的媒介是机械盘,所以离散的写操作性能很差,因此为了弥补这个,设计了重做日志,重做日志的操作是顺序IO,同时重做日志也比较方便用来复制变化量到standby。
acid中d实际上指的就是事务结束时对数据库产生的修改对应redo数据的持久化。redo非常重要,商用数据库支持写多份redo,例如oracle通过创建redo group支持:
```
Add the mirrored groups:
alter database add logfile group 1 ('/oracle/SAL/origlogB/log_g11m1.dbf', '/oracle/SAL/mirrlogB/log_g11m2.dbf') size 100 M;
alter database add logfile group 2 ('/oracle/SAL/origlogA/log_g12m1.dbf', '/oracle/SAL/mirrlogA/log_g12m2.dbf') size 100 M;
```
目前PG暂时不支持mirror redo的功能,但是有一些变通的方法:
1、使用多个块设备 + zfs类似的文件系统 构建mirror
2、pg_receivewal + sync replication
本文介绍方法2,通过pg自身的同步流复制 + pg_receivewal实现多份wal存储。
1 同步流复制
https://www.postgresql.org/docs/12/runtime-config-replication.html#GUC-SYNCHRONOUS-STANDBY-NAMES
[FIRST] num_sync ( standby_name [, ...] )
ANY num_sync ( standby_name [, ...] )
standby_name [, ...]
配置例子
```
standby1: recovery.conf > 'conn info -> application_name=s1'
standby2: recovery.conf > 'conn info -> application_name=s2'
standby3: recovery.conf > 'conn info -> application_name=s3'
standby4: recovery.conf > 'conn info -> application_name=s4'
primary: synchronous_standby_names :
FIRST 3 (s1, s2, s3, s4) 表示前三个为sync standby,后面的都是potential standby,前面不足3个时,接下来的potential standby自动升级为sync standby。
ANY 3 (s1, s2, s3, s4) 表示任意3个都可以为sync standby。
```
2 实时接收 wal
https://www.postgresql.org/docs/12/app-pgreceivewal.html
pg_receivewal [option...]
通过流复制协议,实时接收上游的redo信息。
3 配置多份 wal
例如要求本地写一份wal,同时异地写一份wal. 可以配置如下:
synchronous_standby_names='ANY 1 (s1, s2)'
synchronous_commit=remote_write
同时配置两个不同的异地pg_receivewal , 但是事务提交时,根据以上配置要求redo本地持久化,同时至少有一个receiver端收到redo。
当本地wal挂了,可以从两个receiver目标端,选择接收最多的那个,并使用如下方法配置,做到0丢失。
```
restore_command = 'cp /walarchive/%f %p || cp /walarchive/%f.partial %p'
.partial表示这个wal文件还没有写完,只有部分内容。如果是归档,没有写完的wal是不会归档的,而wal receiver可以实时接收wal,做到0丢失。
```
小结
通过同步流复制,pg_receivewal流士接收wal客户端,实现wal的mirror,即使本地wal文件损坏也不丢失事务。确保0丢失。
参考
https://www.cybertec-postgresql.com/en/never-lose-a-postgresql-transaction-with-pg_receivewal/
https://www.postgresql.org/docs/12/app-pgreceivewal.html
https://www.postgresql.org/docs/12/runtime-config-replication.html#GUC-SYNCHRONOUS-STANDBY-NAMES
PostgreSQL 许愿链接
您的愿望将传达给PG kernel hacker、数据库厂商等, 帮助提高数据库产品质量和功能, 说不定下一个PG版本就有您提出的功能点. 针对非常好的提议,奖励限量版PG文化衫、纪念品、贴纸、PG热门书籍等,奖品丰富,快来许愿。开不开森.
9.9元购买3个月阿里云RDS PostgreSQL实例
PostgreSQL 解决方案集合
德哥 / digoal's github - 公益是一辈子的事.





