数据库内核月报 - 2015 / 10-PgSQL · 特性分析 · PG主备流复制机制
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交互主要分为以下几个步骤:
walreceiver启动后通过recovery.conf文件中的primary_conninfo参数信息连向主库,主库通过连接参数replication=true启动walsender进程; walreceiver执行identify_system命令,获取主库systemid/timeline/xlogpos等信息,执行TIMELINE_HISTORY命令拉取history文件; 执行wal_startstreaming开始启动流复制,通过walrcv_receive获取WAL日志,期间也会回应主库发过来的心跳信息(接收位点、flush位点、apply位点),向主库发送feedback信息(最老的事务id),避免vacuum删掉备库正在使用的记录; 执行walrcv_endstreaming结束流复制,等待startup进程更新receiveStart和receiveStartTLI,一旦更新,进入步骤2。图2. PG流复制过程
walreceiver和startup进程startup进程进入standby模式和apply日志主要过程:
读取pg_control文件,找到redo位点;读取recovery.conf,如果配置standby_mode=on则进入standby模式。 如果是Hot Standby需要初始化clog、subtrans、事务环境等。初始化redo资源管理器,比如Heap、Heap2、Database、XLOG等。 读取WAL record,如果record不存在需要调用XLogPageRead- WaitForWALToBecomeAvailable- RequestXLogStreaming唤醒walreceiver从walsender获取WAL record。对读取的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掉。
检查一致性,如果一致了,Hot Standby模式可以接受用户只读查询;更新共享内存中XLogCtlData的apply位点和时间线;如果恢复到时间点,时间线或者事务id需要检查是否恢复到当前目标; 回到步骤3,读取next WAL record。PgSQL · 特性分析 · 数据库崩溃恢复(下) 在上期月报PgSQL · 特性分析 · 数据库崩溃恢复(上),我们分析了PostgreSQL在数据库非正常退出后(包括通过recovery.conf用户主动恢复)的处理,概括起来分为以下几步:
PgSQL · 特性分析 · 数据库崩溃恢复(上) 为了合并I/O提高性能,PostgreSQL数据库引入了共享缓冲区,当数据库非正常关闭,比如服务器断电时,共享缓冲区即内存中的数据就会丢失,这个时候数据库操作系统重启时就需要从非正常状态中恢复过来,继续提供服务。本文将具体分析在这种情况下,PostgreSQL数据库如何从崩溃状态中恢复。 上期月报PgSQL · 特性分析 · checkpoint机制浅析中介绍了PostgreSQL中的c
PgSQL · PostgreSQL 逻辑流复制技术的秘密 自 PostgreSQL 9.4 ,终于支持了逻辑流复制。本篇文章为大家带来这部分的技术细节的分析。 1. 背景 PostgreSQL 9.4 对逻辑流复制的支持具有相当的意义。我们可以用该技术完成很多企业级的需求。
PostgreSQL 的大版本升级,由于可以使用流复制做增量数据同步,所以停机服务时间会非常短。 PostgreSQL 自定义逻辑拆库。由于是逻辑数据,所以很容易自定义分发
MySQL · 引擎特性 · MySQL5.7 崩溃恢复优化 在MySQL5.7之前的版本中, InnoDB每次做crash recovery之前都需要扫描数据目录,打开每个文件并创建内存对象。当目录下文件个数特别多时,会严重影响到崩溃恢复的速度。 为了解决这个问题,MySQL5.7通过结合checkpoint + 标注被修改的文件的方式,从一个check
db匠 rds内核团队秘密研发的全自动卖萌机. 追加特效: 发数据库内核月报. 月报传送: http://mysql.taobao.org/monthly/
相关文章
- [SZU] 数据库内核课程 PostgreSQL 12.5 源码安装避坑 guide
- SQLServer 错误 4064 无法打开用户默认数据库。 登录失败。 故障 处理 修复 支持远程
- Oracle的nvl函数和nvl2函数详解数据库
- 优化MySQL内核优化:提升数据库性能(mysql内核)
- 解析MongoDB数据库路径:了解其结构与使用方法(mongodb数据库路径)
- MySQL数据库编码设置方法(mysql如何设置编码)
- 深入了解Oracle数据库结构与构成(oracle数据库的构成)
- MySQL数据库:保存智能未来(mysql 保存)
- PHP连接MSSQL数据库快速开启(php mssql 打开)
- Oracle数据库:从启动到运行(启动 oracle数据库)
- 构建Oracle数据库用户:一步一步指导(oracle数据库建用户)
- 深入探讨Oracle数据库内核参数查看方法(oracle内核参数查看)
- 优化Oracle数据库提升内存可以更有效(oracle 内存增大)