0

Postgres 通过 WAL(Write Ahead Log) 文件支持主从复制。

在主服务器上,一个被调用的后端进程WALSender会将日志文件(记录)发送到从服务器,在从服务器上,一个被调用的后端进程WALReceiver将接收日志文件(记录),并将块数据而不是 SQL 查询存储在 WAL 文件中. (我对吗??)

那么从服务器如何在基于文件的复制和流复制的情况下应用日志更新呢?我的意思是详细地说哪个进程处理这个以及它是如何做到的?

提前致谢。

4

1 回答 1

2

你的描述是一个合理的总结,是的。大致分为三个层次:

  • 高级 SQL 查询,例如“UPDATE mytable SET a=nextval('some_sequence'), b=current_timestamp WHERE id=$1”

  • 逻辑行更改,例如“在主键值 id=42 的表 abc 中,元组已更新为新值(a=11,b=12314234321)”。这些不是以这种形式记录在磁盘上的,而是在执行器内部产生的一个中间阶段,然后变成:

  • 写入 xlog 然后写入堆的块级更改,例如“与存储在表空间 1 中的 dboid 9191 中的 relfilenode 12312.1 相关,块 41231 字节偏移量 0x0012 更改为 0xde 0xad 0xbe 0xef 0x01”

(所有数字完全编造)

基于 WAL 的复制发生在最低级别,记录数据库中文件的块更改。好的,所以它不是那么简单,但为了理解复制的目的,这样做是可行的。

在独立的 master 上,SQL 被执行,产生记录到 WAL 和shared_buffers. 然后重放 WAL 以将更改应用到数据库堆。(同样,由于 bgwriter 的脏写回等原因,这并不是那么简单,但现在可以使用)。

使用基于 WAL 的复制,主服务器保留 WAL - 将其发送到副本或存档。副本,而不是生成自己的 WAL 然后重放它,只需从其他地方的 master 重放 WAL,使用它来更新数据库堆和它们的shared_buffers.

那么从服务器如何在基于文件的复制的两种情况下应用日志更新

当副本restore_command到达上一个存档的末尾时,它会运行以请求下一个 WAL 存档。然后恢复过程开始读取 WAL 存档,逐个记录地处理它。

查看restore_command源代码中如何使用它以了解它是如何调用的。

和流复制?

副本的 walreceiver 连接到上游的 walsender 并接收 wal 记录。这些被写入一个文件,然后恢复过程读取该文件。

在这两种情况下,恢复部分是相同的,不同之处在于如何从上游接收 WAL。在 master 上进行崩溃恢复时,恢复也大致相同。这也只是重播 WAL。

我的意思是详细地说哪个进程处理这个以及它是如何做到的?

最好的参考是源代码——特别是注释和自述文件。

我强烈建议您使用pg_xlogdump查看 WAL 实际包含的内容。然后阅读相关 WAL 记录的文档以了解每种记录类型的作用。

也从阅读src/backend/access/transam/README和开始src/backend/access/transam/xlog.c

我不会重复相关自述文件中已经包含的内容,这些自述文件比我的描述更可能是正确的。

于 2015-10-16T04:49:00.843 回答