你的描述是一个合理的总结,是的。大致分为三个层次:
高级 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 在源代码中是如何使用的,看看它是如何被调用的。
还有流式复制?
replica 的 walreceiver 连接到上游的 walsender 并接收 wal 记录。这些被写入一个文件,然后恢复过程会读取该文件。
recovery 部分在这两种情况下是相同的,不同之处在于 WAL 是如何从上游接收的。在 master 上进行崩溃恢复时,恢复也大致相同。这也只是重播 WAL。
我的意思是详细地说是哪个进程处理这个以及它是如何做到的?
最好的参考是源代码 - 特别是 cmets 和 README 文件。
我强烈建议您使用pg_xlogdump 来查看 WAL 实际包含的内容。然后阅读相关 WAL 记录的文档以了解每种记录类型的作用。
也从阅读src/backend/access/transam/README 和src/backend/access/transam/xlog.c 开始。
我不会重复相关 README 中已经包含的内容,它们比我的描述更可能是正确的。