网站建设及报价,app制作教程课,淮北市建设投资有限责任公司,广西建设网桂建云网站PostgreSQL 9.4 开始支持Replication Slot新功能。对于Replication Slot#xff0c;文档上介绍的不多#xff0c;乍一看让人比较难理解是做什么的。其实#xff0c;Replication Slot的出现#xff0c;主要是为最终在PG内核实现逻辑复制和双向复制铺路的#xff08;目前文档上介绍的不多乍一看让人比较难理解是做什么的。其实Replication Slot的出现主要是为最终在PG内核实现逻辑复制和双向复制铺路的目前逻辑和双向复制在内核中还缺少很多核心功能点需要借助BDR插件见PG官方wiki 引入Replication Slot的背后原因见这里。不过作为9.4版本的一个主要功能它不但可以用于逻辑复制还可用于物理复制或者叫Streaming Replication。针对物理复制的Replication Slot称为Physical Replication Slot。
由于大家目前主要用的还只是PG自带的物理复制方式我们就重点分析一下Physical Replication Slot。
使用Physical Replication Slot可以达到两个效果
A可以确保从库standby需要的日志不被过早备份出去而导致从库失败出现下面的error
ERROR: requested WAL segment 00000001000000010000002D has already been removed通过Replication Slot记录的从库状态PG会保证从库还没有apply的日志不会从主库的日志目录里面清除或archive掉。而且replication slot的状态信息是持久化保存的即便从库断掉或主库重启这些信息仍然不会丢掉或失效。
B当允许应用连接从库做只读查询时Replication Slot可以与运行时参数hot_standby_feedback配合使用使主库的vacuum操作不会过早的清掉从库查询需要的记录而出现如下错误错误的原因下面会详细解释
ERROR: canceling statement due to conflict with recovery下面看看Physical Replication Slot的用法和内核实现。
用法
下面是启用Replication Slot的步骤很简单
1首先需要配置好Steaming Replication的主库从库。涉及的参数有listen_addresses*hot_standbyon wal_levelhot_standbymax_wal_senders1尤其注意配置max_replication_slots大于等于1。这些参数主从库应一致。
2在主库创建replication slot
postgres# SELECT * FROM pg_create_physical_replication_slot(#039;my_rep_slot_1#039;);
slot_name | xlog_position
------------------------------
my_rep_slot_1 |此时replication slot还不处于active状态。
3) 在从库配置recovery.conf如下然后重启从库
standby_mode #039;on#039;
primary_slot_name #039;my_rep_slot_1#039;
primary_conninfo #039;userpg001 host10.x.x.x port5432 sslmodeprefer sslcompression1 krbsrvnamepostgres#039;4观察主库replication slot的状态变化
postgres# SELECT * FROM pg_replication_slots ;
slot_name | plugin | slot_type | datoid | database | active | xmin | catalog_xmin | restart_lsn
---------------------------------------------------------------------------------------------
my_rep_slot_1 | | physical | | | t | 1812 | | 0/3011A705与hot_standby_feedback配合使用。在将从库的postgresql.conf文件中的hot_standby_feedback选项设为on重启从库即可。
内核实现
replication slot是由下面的patch加入内核中的
author Robert Haas lt;rhaaspostgresql.orggt;
Sat, 1 Feb 2014 03:45:17 0000 (22:45 -0500)
committer Robert Haas lt;rhaaspostgresql.orggt;
Sat, 1 Feb 2014 03:45:36 0000 (22:45 -0500)
Replication slots are a crash-safe data structure which can be created
on either a master or a standby to prevent premature removal of
write-ahead log segments needed by a standby, as well as (with
hot_standby_feedbackon) pruning of tuples whose removal would cause
replication conflicts. Slots have some advantages over existing
techniques, as explained in the documentation.这个patch改的文件不少分析这些代码我们重点关注下面的问题
AReplication Slot是如何在内核中创建的
通过分析创建Replication Slot时调用的函数ReplicationSlotCreate可以看出Replication Slot实质上是内存中的一些数据结构加上持久化保存到pg_replslot/目录中的二进制状态文件。在PG启动的时候预先在共享内存中分配好这些数据结构所用内存即一个大小为max_replication_slots的数组。这些数据结构在用户创建Replication Slot时开始被使用。一个Replication Slot被创建并使用后其数据结构和状态文件会被WALWrite-Ahead-Log的发送者wal_sender)进程更新。
另外如果单纯从Replication Slot的名字我们很容易觉得Replication Slot会创建新的与从库的连接进行日志发送。实际上创建过程中并没有创建新的与从库的连接Replication Slot还是使用了wal_sender原有连接由于一个从库一个wal_sender连接所以一个从库和主库之间也只有一个active的Replication Slot。
B) Replication Slot的状态是如何被更新的
很容易发现Replication Slot的状态的更新有两种情况。
第一种是在ProcessStandbyHSFeedbackMessage这个函数被更新。这个函数是在处理wal_sender所收到的从库发回的feedback reply message时调用的。通过这个函数我们可以看出每个wal_sender进程的Replication Slot就是用户创建的Replication Slot保存在MyReplicationSlot这个全局变量中。在处理从库发回的reply时reply中的xmin信息会被提取出来存入slot的data.xmin和effective_xmin域中并通过函数ProcArraySetReplicationSlotXmin最终更新到系统全局的procArray-replication_slot_xmin结构中以使其对所有进程可见完成slot的更新。
这里要注意如果我们有多个Replication Slot分别对应各自从库则在更新全局结构procArray-replication_slot_xmin时会选取所有slot中最小的xmin值。
第二种是在ProcessStandbyReplyMessage中。这个函数处理从库发送的restart lsn信息即从库apply的日志的编号会直接将其更新到replication slot的restart lsn域中并保存到磁盘用于主库判断是否要保留日志不被archive。
C) Replication Slot如何和hot_standby_feedback配合来避免从库的查询冲突的
这里从库的查询冲突指的是下面的情况从库上有正在运行的查询而且运行时间很长这时主库上在做正常的vaccum清除掉无用的记录版本。但主库的vaccum是不知道从库的查询存在的所以在清除时不考虑从库的正在运行的查询只考虑主库里面的事务状态。其结果vacuum可能会清除掉从库查询中涉及的仍然在使用的记录版本。当这些vaccum操作通过日志同步到从库而恰好从库的查询仍然没有运行完vaccum就要等待或cancel这个查询以保证同步正常继续和查询不出现错误的结果。这样每当用户在从库运行长查询就容易出现我们上面提到到query conflict error。
如何避免这种冲突呢目前最好的解决方案是使用hot_standby_feedback Replication Slot。其原理简单说就是从库将它的查询所依赖的记录版本的信息以一个事务id来表示并放在从库发回给主库wal_sender的reply中发给主库见函数XLogWalRcvSendHSFeedback并最终传导给主库vaccum让其刀下留人暂时不清除相关记录。
具体过程是在从库函数XLogWalRcvSendHSFeedback调用GetOldestXmin获得xmin放入给主库的reply中。主库的wal_sender收到后如果使用了Replication Slot就把这个xmin放入slot的状态信息中并更新此时系统所有slot的最小xmin。这个系统所有slot的最小xmin怎么在主库传导给vacuum的呢以自动触发的vacuum操作为例其中的逻辑的顺序如下
GetSnapshotDatavacuum事务开始时获取slot xmin存入全局变量 -vacuum_set_xid_limits调用 GetOldestXmin通过全局变量获取系统xmin和slot xmin取较小值- vacuum_lazy 使用xmin判断哪些记录版本可以清除
这样利用Replication Slot这个渠道就解决了从库查询冲突。
注意事项
最后介绍一下使用Replication Slot的注意事项
1如果收不到从库的replyReplication Slot的状态restart lsn会保持不变造成主库会一直保留本地日志可能导致日志磁盘满。所以应该实时监控日志磁盘使用情况并设置较小的wal_sender_timeout及早发现从库断掉的情况。
2将hot_standby_feedback设为on时注意如果从库长时间有慢查询发生可能导致发回到主库的xmin变化较慢主库的vaccum操作停滞造成主库被频繁更新的表大小暴增。
除了物理复制Replication Slot对逻辑复制的意义更大我们期待在可能出现逻辑复制功能的9.5版本中看到它大显身手。