本文共 2041 字,大约阅读时间需要 6 分钟。
PostgreSQL 9.0 引入了主备流复制机制,通过流复制,备库从主库同步数据并应用WAL记录。流复制每次传输单位是WAL日志的record,而9.0之前的方法是主库写完一个WAL日志文件后传送给备库,导致主备延迟较大。9.0之后还引入了Hot Standby,备库在应用WAL记录的同时提供只读服务,提升了用户体验。
PG主备流复制的核心部分由walsender、walreceiver和startup三个进程组成。walsender负责发送WAL日志记录,执行顺序如下:
PostgresMain() -> exec_replication_command() -> StartReplication() -> WalSndLoop() -> XLogSendPhysical()
walreceiver负责接收WAL日志记录,执行顺序如下:
sigusr1_handler() -> StartWalReceiver() -> AuxiliaryProcessMain() -> WalReceiverMain() -> walrcv_receive()
startup进程负责应用日志,执行顺序如下:
PostmasterMain() -> StartupDataBase() -> AuxiliaryProcessMain() -> StartupProcessMain() -> StartupXLOG()
walsender和walreceiver交互主要分为以下几个步骤:
walreceiver启动后通过recovery.conf文件中的primary_conninfo参数连接主库,主库通过replication=true启动walsender进程。walreceiver执行identify_system命令,获取主库的systemid、timeline和xlogpos等信息,执行TIMELINE_HISTORY命令拉取历史文件。wal_startstreaming开始流复制,通过walrcv_receive获取WAL日志,期间回应主库发来的心跳信息(接收位点、flush位点、apply位点),向主库发送反馈信息(最老的事务ID),避免vacuum删掉备库正在使用的记录。walrcv_endstreaming结束流复制,等待startup进程更新receiveStart和receiveStartTLI,一旦更新,进入步骤2。walsender和walreceiver的交互流程如下:
walreceiver启动后通过recovery.conf文件中的primary_conninfo参数连接主库,主库通过replication=true启动walsender进程。walreceiver执行identify_system命令获取主库信息,执行TIMELINE_HISTORY拉取历史文件。wal_startstreaming开始流复制,通过walrcv_receive获取WAL日志,期间回应主库发来的心跳信息,向主库发送反馈信息。walrcv_endstreaming结束流复制,等待startup进程更新receiveStart和receiveStartTLI,一旦更新,进入步骤2。startup进程进入Hot Standby模式和应用日志的主要过程如下:
pg_control文件,找到redo位点;读取recovery.conf文件,如果配置standby_mode=on则进入standby模式。XLogPageRead->WaitForWALToBecomeAvailable->RequestXLogStreaming唤醒walreceiver从walsender获取WAL记录。record->xl_rmid信息调用相应的redo资源管理器进行操作,如XLOG_HEAP_INSERT。XLogCtlData的apply位点和时间线;如果恢复到时间点、时间线或事务ID需要检查是否恢复到当前目标。通过以上流程,PostgreSQL实现了高效的主备流复制机制,减少了主备延迟,并通过Hot Standby模式提供了只读服务,显著提升了用户体验。
转载地址:http://mmvfk.baihongyu.com/