原文地址:http://mysql.taobao.org/monthly/2015/10/04/

PostgreSQL在9.0之后引入了主备流复制机制,通过流复制,备库不断的从主库同步相应的数据,并在备库apply每个WAL record,这里的流复制每次传输单位是WAL日志的record。而PostgreSQL9.0之前提供的方法是主库写完一个WAL日志文件后,才把WAL日志文件传送到备库,这样的方式导致主备延迟特别大。同时PostgreSQL9.0之后提供了Hot Standby,备库在应用WAL record的同时也能够提供只读服务,大大提升了用户体验。

主备总体结构

PG主备流复制的核心部分由walsender,walreceiver和startup三个进程组成。 walsender进程是用来发送WAL日志记录的,执行顺序如下:

PostgresMain()->exec_replication_command()->StartReplication()->WalSndLoop()->XLogSendPhysical()

walreceiver进程是用来接收WAL日志记录的,执行顺序如下:

sigusr1_handler()->StartWalReceiver()->AuxiliaryProcessMain()->WalReceiverMain()->walrcv_receive()

startup进程是用来apply日志的,执行顺序如下:

PostmasterMain()->StartupDataBase()->AuxiliaryProcessMain()->StartupProcessMain()->StartupXLOG()

下图是PG主备总体框架图:

图1. PG主备总体框架图

walsender和walreceiver进程流复制过程

walsender和walreceiver交互主要分为以下几个步骤:

  1. walreceiver启动后通过recovery.conf文件中的primary_conninfo参数信息连向主库,主库通过连接参数replication=true启动walsender进程;
  2. walreceiver执行identify_system命令,获取主库systemid/timeline/xlogpos等信息,执行TIMELINE_HISTORY命令拉取history文件;
  3. 执行wal_startstreaming开始启动流复制,通过walrcv_receive获取WAL日志,期间也会回应主库发过来的心跳信息(接收位点、flush位点、apply位点),向主库发送feedback信息(最老的事务id),避免vacuum删掉备库正在使用的记录;
  4. 执行walrcv_endstreaming结束流复制,等待startup进程更新receiveStart和receiveStartTLI,一旦更新,进入步骤2。

图2. PG流复制过程

walreceiver和startup进程

startup进程进入standby模式和apply日志主要过程:

  1. 读取pg_control文件,找到redo位点;读取recovery.conf,如果配置standby_mode=on则进入standby模式。
  2. 如果是Hot Standby需要初始化clog、subtrans、事务环境等。初始化redo资源管理器,比如Heap、Heap2、Database、XLOG等。
  3. 读取WAL record,如果record不存在需要调用XLogPageRead->WaitForWALToBecomeAvailable->RequestXLogStreaming唤醒walreceiver从walsender获取WAL record。
  4. 对读取的WAL record进行redo,通过record->xl_rmid信息,调用相应的redo资源管理器进行redo操作。比如heap_redo的XLOG_HEAP_INSERT操作,就是通过record的信息在buffer page中增加一个record:

     MemSet((char *) htup, 0, sizeof(HeapTupleHeaderData));
    /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */
    memcpy((char *) htup + offsetof(HeapTupleHeaderData, t_bits),
    (char *) xlrec + SizeOfHeapInsert + SizeOfHeapHeader,
    newlen);
    newlen += offsetof(HeapTupleHeaderData, t_bits);
    htup->t_infomask2 = xlhdr.t_infomask2;
    htup->t_infomask = xlhdr.t_infomask;
    htup->t_hoff = xlhdr.t_hoff;
    HeapTupleHeaderSetXmin(htup, record->xl_xid);
    HeapTupleHeaderSetCmin(htup, FirstCommandId);
    htup->t_ctid = xlrec->target.tid; offnum = PageAddItem(page, (Item) htup, newlen, offnum, true, true);
    if (offnum == InvalidOffsetNumber)
    elog(PANIC, "heap_insert_redo: failed to add tuple"); freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */ PageSetLSN(page, lsn); if (xlrec->flags & XLOG_HEAP_ALL_VISIBLE_CLEARED)
    PageClearAllVisible(page); MarkBufferDirty(buffer);

    还有部分redo操作(vacuum产生的record)需要检查在Hot Standby模式下的查询冲突,比如某些tuples需要remove,而存在正在执行的query可能读到这些tuples,这样就会破坏事务隔离级别。通过函数ResolveRecoveryConflictWithSnapshot检测冲突,如果发生冲突,那么就把这个query所在的进程kill掉。

  5. 检查一致性,如果一致了,Hot Standby模式可以接受用户只读查询;更新共享内存中XLogCtlData的apply位点和时间线;如果恢复到时间点,时间线或者事务id需要检查是否恢复到当前目标;
  6. 回到步骤3,读取next WAL record。

图3. PG standby模式和apply日志过程

PgSQL · 特性分析 · PG主备流复制机制的更多相关文章

  1. PostgreSQL主备流复制机制

    原文出处 http://mysql.taobao.org/monthly/2015/10/04/ PostgreSQL在9.0之后引入了主备流复制机制,通过流复制,备库不断的从主库同步相应的数据,并在 ...

  2. KingbaseES V8R6集群部署案例之---Windows环境配置主备流复制(异机复制)

    案例说明: 目前KingbaseES V8R6的Windows版本不支持数据库sys_rman的物理备份,可以考虑通过建立主备流复制实现数据库的异机物理备份.本案例详细介绍了,在Windows环境下建 ...

  3. KingbaseES V8R6集群部署案例之---Windows环境配置主备流复制(同一主机)

    案例说明: 目前KingbaseES V8R6的Windows版本不支持数据库sys_rman的物理备份,可以考虑通过建立主备流复制实现数据库的异机物理备份.本案例详细介绍了,在Windows环境下建 ...

  4. KingbaseES R6 主备流复制集群创建级联复制案例

    案例环境: 数据库: test=# select version(); version -------------------------------------------------------- ...

  5. pgpool-II主备流复制的架设

    1.环境 OS: CentOS release 6.4 (Final) DB: postgresql 9.3.6 pgpool服务器: pgpool 172.16.0.240 数据库主服务器:mast ...

  6. KingbaseES R6 手工创建主备流复制案例

    ​ 数据库版本: TEST=# select version(); version ---------------------------------------------------------- ...

  7. [原创] PostgreSQL Plus Advanced Server在Windows中配置双机热备流复制

    一.系统环境 操作系统:Windows Server 2003/2008 两个节点分别为master与slave. 主节点master:172.27.19.28 备机点slave:172.27.19. ...

  8. PgSQL · 特性分析 · 谈谈checkpoint的调度

    在PG的众多参数中,参数checkpoint相关的几个参数颇为神秘.这些参数与checkpoint的调度有关,对系统的稳定性还是比较重要的,下面我们为大家解析一下,这要先从PG的数据同步机制谈起. P ...

  9. PostgreSQL流复制

    原理机制 参考--https://yq.aliyun.com/articles/51009 主备总体结构 PG主备流复制的核心部分由walsender,walreceiver和startup三个进程组 ...

随机推荐

  1. ARC模式下delloc()注意事项

    1.ARC模式下delloc()调用触发时机是对象被销毁,如self.属性=nil 2.ARC模式下delloc()里面不需要手动调用[super dealloc]; 因为系统已经自动调用,多此一举的 ...

  2. vi set the tab width for python

    Put your desired settings in the ~/.vimrc file -- See below for some guidelines and best practices. ...

  3. ASP.NET超大文件上传与下载

    总结一下大文件分片上传和断点续传的问题.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件 ...

  4. android平台上AES,DES加解密及问题

    在使用java进行AES加密的时候,会用到如下方法: SecureRandom sr = SecureRandom.getInstance("SHA1PRNG"); 但是在andr ...

  5. Vim 编辑器学习笔记

    参考资料: 世界上最牛的编辑器: Vim 1

  6. php WebSocket 简单实现demo

    WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据. 在 ...

  7. 从 Quora 的 187 个问题中学习机器学习和NLP

    从 Quora 的 187 个问题中学习机器学习和NLP 原创 2017年12月18日 20:41:19 作者:chen_h 微信号 & QQ:862251340 微信公众号:coderpai ...

  8. 在php中获取 数据库的内容,返回到页面

    <?php header("content-type:text/html;charset=utf-8"); $link=mysqli_connect("localh ...

  9. windows编程,消息函数中拦截消息的问题

    很多年没有写windows窗口程序了,今天自制基于vulkan的程序时遇到了一些问题,部分代码如下: LRESULT CALLBACK XWindow::WndProc(HWND hWnd, UINT ...

  10. 快速获取批量处理Docker镜像SQL语句

    .获取批量pull语句 select concat('docker pull develop-harbor.geostar.com.cn/', t.name, ':', t1.tag) name fr ...