PostgreSQL 本身的复制方式和方法是有一个渐进的历史,这段历史也是证明POSTGRESQL 为何能走到今天越来越热的原因。


注:以下部分内容的命名(仅仅根据在 PG11 中的功能命名,方便不知道历史的亲们迷糊)


第一幅图是来自于 2006年的 PG 8.X


PostgreSQL 复制历史与简单的stream replication monitor_mysql

通过上面的图,大家应该可以很清楚的理解,这一时期的复制方式有点类似于到现在还活跃在数据复制方式一线的 SQL SERVER 的 shipping log


这样的方式优势是简单,有效并且很多场合的兼容性比较高(例如SQL SERVER  的 replication 虽然可以表级别的进行复制,但对表的要求也高,同时动不动的新功能(2016)的历史表)就不被支持复制。


这段的意思就是PG 在2006年的时候就具有了SQL SERVER 的 shipping log的功能进行数据的复制。当然这样的复制方式缺点也是显而易见的。


如果主服务器上的事务由于网络,或者其他主机的原因未复制到从库,则数据就丢失了(在主库无法恢复的情况下)。


所以PostgreSQL 很快在 2010 年PG 9 的时候,采用了类似 ORACLE streams Replication 的机制,这样的机制保证了数据同步在很多时候(如果你采用的是异步同步)数据两端是一致的。如果你开启了同步的模式则数据必然是一致的(当然很少人这么干,为什么?)


PostgreSQL 复制历史与简单的stream replication monitor_mysql_02

当然这样的方式也是有问题的,如果wal log 清理的速度比复制的速度快,则standby 将复制不到数据,其实这个道理和  MYSQL的 BINLOG 复制有点雷同,(但原理上不一样),如果你把MYSQL 的BINLOG 的数据未复制到从库,就删除了,那你的主从复制一定会失败。


所以 PostgreSQL 在 9.4 的时候引入了复制槽的概念,如果从库由于某些原因没有接受到数据或者断掉了,则主库会在复制槽中保留从库没有接受到的数据,一直到从库连接上,开始进行复制。


所以PG 的流复制是可靠的,安全的,值得信赖的(当然如果你不开启复制槽,可不是PG的错)



当然PG 的脚步并未停止,在PG 10的时候,又支持了逻辑复制,这个功能类似于 SQL SERVER 的 publication 和 replication 的功能。他可以单独的复制某一个你想复制的表到对应的订阅的PG 中,利用逻辑复制槽来进行数据复制,比SQL SERVER 复制订阅貌似要靠谱的多。


当然在PG 的复制中,一主多从的复制方式也是OK的,类似MYSQL 的复制方式,但比MYSQL的复制方式要高效安全。你不会担心主从某些表的数据不一致的问题发生。


总结成一个图的话

PostgreSQL 复制历史与简单的stream replication monitor_sql_03

当然任何事情或人十全十美都是一个美好的愿望,PG 如果说要挑选出来缺点的话,就是高可用的方式目前还处于五代十国的阶段,各种的高可用和切换的方式各有各的特点,但也都有自己的问题。如同MYSQL 在被 ORACLE 收购前的状态,好似看到那个曾经自由过的MYSQL。



说道这里,如何监控PG 中的流复制的数据同步的状态,来鉴别数据复制中从库是否与主库不同步,怎么鉴别相关状态。下面有一些简单的方法,(未提及某些开源的插件的方法)


1  在主库中可以通过  select * from pg_stat_replication;

来查看当前与主库进行数据同步的从库 的信息,如下图包含了从库的地址,接受数据的端口,数据复制的开始时间,发送的lsn 号等信息

PostgreSQL 复制历史与简单的stream replication monitor_mysql_04


2 当然在从库中运行 select * from pg_stat_wal_receiver; 

同样可以获得,从库连接的主库信息,IP , 对方开始发送数据的时间,本地接受数据的时间,接受和进行重写的LSN 号。(如果图中的部分信息和你在你的从库中展示的信息不一致,是由于目前截图的两台机器做了 repmgr)

PostgreSQL 复制历史与简单的stream replication monitor_sql_05


3 同时 PG 也提供了一些函数来辅助判断LSN

​SELECT​​​​CASE​​​​WHEN​​​​pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn()​​​​THEN​​​​0​​​​ELSE​​​​EXTRACT (EPOCH ​​​​FROM​​​​now() - pg_last_xact_replay_timestamp())​​​​END​​​​AS​​​​log_delay;​


这段语句是在从库执行,来判断从库接收到的数据和重放的数据之间有没有差距

PostgreSQL 复制历史与简单的stream replication monitor_sql_06


4 当然也可以在主库上运行,下面的语句,来查看当前的主库从库之间的复制的差距

select
pid,
application_name,
pg_wal_lsn_diff(pg_current_wal_lsn(), sent_lsn) sending_lag,
pg_wal_lsn_diff(sent_lsn, flush_lsn) receiving_lag,
pg_wal_lsn_diff(flush_lsn, replay_lsn) replaying_lag,
pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) total_lag
from pg_stat_replication;

PostgreSQL 复制历史与简单的stream replication monitor_sql_07


PG 目前的复制技术无论在传统的开源还是收费数据库界,绝对都让人印象深刻。



PostgreSQL 复制历史与简单的stream replication monitor_sql_08