postgres数据库的流复制

发布于:2024-07-01 ⋅ 阅读:(42) ⋅ 点赞:(0)

1. 流复制和逻辑复制的差异

  • 逻辑复制和流复制最直观的不同是,逻辑复制支持表级别复制
  • 区分点事原理不同
    • 逻辑日志是在wal日志产生的数据库上,由逻辑解析模块对wal日志进行初步的解析,解析结果是ReorderBufferChange(理解为HeapTupleData),再由pgoutput plugin对中间结果进行过滤和消息化拼接,然后将其发送到订阅端,订阅端根据接受到的Heap TupleData重新对其执行insert、delete、udpate操作
    • 流复制时将数据从walrecord拷贝到数据页,
    • 逻辑复制时将数据重新执行一次insert、update或delete

2. 流复制

  • 流复制面对未提交的事务,事务没有提交也会同步到备机,当主库进行提交和回滚的时候,也会同步进行提交和回滚。对大事务相对友好
  • 流复制会导致备机也会产生大量死元祖,需要做vacuum
  • 流复制时将wal日志中记录的内容按照确切的块地址逐字节的拷贝到备库,因此主备之间数据分布是一样的,意味着主备机器上,同一条记录的ctid是相同的

3. 流复制的实现原理

  • 后端进程通过执行XLogInsert和XLogFlush函数,将wal数据写入并刷新到WAL段文件中
  • walsender进程将写入wal段的wal数据发送给walreveiver进程
  • 发送wal数据后,后端进程继续等待备用服务器的ACK响应。更准确的说,后端进行通过执行内部函数SyncRepWaitForLSN获得一个latch,并等待他被释放
  • 备用服务器上的walreveiver将接受到的wal数据写入备用的wal段中,使用write系统调用,并向walsender返回一次ACK响应
  • walreveiver使用如fsync等系统调用将wal数据刷新到wal段,向walsender返回另一个ACK响应,并通知启动进程关于wal数据的刷新
  • startup进程回访已写入wal段的wal数据
  • 当walsender收到walreveiver的ack响应时,释放后端进程的latch,然后后端进程的提交或中止操作将完成。latch释放的时机取决于参数synchronous_commit,如果设置为on,当收到步骤5的ACK时释放latch,如果设置为remote_wirte,则在收到步骤3的ACK时释放latch

ACK的包括内容

  • 写入最新wal数据的lsn位置
  • 刷新最新wal数据的lsn位置
  • 在启动过程中回放最新wal数据的lsn位置
  • 发送此响应的时间戳

过程分析

  • 主库的进程进行写操作
  • 产生WAL record
  • walsender感知到新的wal,发送给备库
  • 备库接受,写盘再回放

是否发送wal日志与主库事务的提交与否没有关系,但主库是否能提交取决于备库的wal日志写入位置,默认是on的话需要落盘,备库实时回放

注意点

  • 流复制就是借助latch实现主从进程间的协作
  • 流复制场景下,只读事务、子事务的提交以及事务回滚,无需等待备库的ACK

网站公告

今日签到

点亮在社区的每一天
去签到