# 目录

> 《PostgreSQL 技术内幕》中文译稿完整目录：两篇序言与十一章 PostgreSQL 内部机制。

---

LLMS 索引： [llms.txt](/llms.txt)

---

![《PostgreSQL 技术内幕》中文译稿封面](/cover.svg)
{.pgint-book-cover}

这份目录与左侧章节树、页末顺序导航共享同一阅读顺序；章内标题直接来自各页内容。选择任意条目即可进入对应章节或小节。

- [目录](/toc/)
- [作者序](/preface/)
  - [致谢](/preface/#致谢)
  - [作者](/preface/#作者)
- [译者序](/preface2/)
  - [译者](/preface2/#译者)
- [1 数据库集簇、数据库与数据表](/ch1/)
  - [1.1 数据库集簇的逻辑结构](/ch1/#11-数据库集簇的逻辑结构)
  - [1.2 数据库集簇的物理结构](/ch1/#12-数据库集簇的物理结构)
    - [1.2.1 数据库集簇的布局](/ch1/#121-数据库集簇的布局)
    - [1.2.2 数据库布局](/ch1/#122-数据库布局)
    - [1.2.3 表与索引相关文件的布局](/ch1/#123-表与索引相关文件的布局)
    - [1.2.4 表空间](/ch1/#124-表空间)
  - [1.3 堆表文件的内部布局](/ch1/#13-堆表文件的内部布局)
  - [1.4 读写元组的方式](/ch1/#14-读写元组的方式)
    - [1.4.1 写入堆元组](/ch1/#141-写入堆元组)
    - [1.4.2 读取堆元组](/ch1/#142-读取堆元组)
- [2 进程和内存架构](/ch2/)
  - [2.1 进程架构](/ch2/#21-进程架构)
    - [2.1.1 Postgres服务器进程](/ch2/#211-postgres服务器进程)
    - [2.1.2 后端进程](/ch2/#212-后端进程)
    - [2.1.3 后台进程](/ch2/#213-后台进程)
  - [2.2 内存架构](/ch2/#22-内存架构)
    - [2.2.1 本地内存区域](/ch2/#221-本地内存区域)
    - [2.2.2 共享内存区域](/ch2/#222-共享内存区域)
- [3 查询处理](/ch3/)
  - [3.1 概览](/ch3/#31-概览)
    - [3.1.1 解析器（Parser）](/ch3/#311-解析器parser)
    - [3.1.2 分析器（Analyzer）](/ch3/#312-分析器analyzer)
    - [3.1.3 重写器（Rewriter）](/ch3/#313-重写器rewriter)
      - [视图](/ch3/#视图)
    - [3.1.4 计划器与执行器](/ch3/#314-计划器与执行器)
      - [pg_hint_plan](/ch3/#pg_hint_plan)
  - [3.2 单表查询的代价估计](/ch3/#32-单表查询的代价估计)
    - [3.2.1 顺序扫描](/ch3/#321-顺序扫描)
    - [3.2.2 索引扫描](/ch3/#322-索引扫描)
      - [3.2.2.1 启动代价](/ch3/#3221-启动代价)
      - [3.2.2.2 运行代价](/ch3/#3222-运行代价)
      - [选择率](/ch3/#选择率)
        - [索引相关性（index correlation）](/ch3/#索引相关性index-correlation)
      - [3.2.2.3 整体代价](/ch3/#3223-整体代价)
        - [seq_page_cost和random_page_cost](/ch3/#seq_page_cost和random_page_cost)
    - [3.2.3 排序](/ch3/#323-排序)
  - [3.3 创建单表查询的计划树](/ch3/#33-创建单表查询的计划树)
    - [3.3.1 预处理](/ch3/#331-预处理)
    - [3.3.2 找出代价最小的访问路径](/ch3/#332-找出代价最小的访问路径)
      - [3.3.2.1 例1](/ch3/#3321-例1)
      - [3.3.2.2 例2](/ch3/#3322-例2)
    - [3.3.3 创建计划树](/ch3/#333-创建计划树)
      - [3.3.3.1 例1](/ch3/#3331-例1)
      - [3.3.3.2 例2](/ch3/#3332-例2)
  - [3.4 执行器如何工作](/ch3/#34-执行器如何工作)
    - [临时文件](/ch3/#临时文件)
  - [3.5 连接](/ch3/#35-连接)
    - [3.5.1 嵌套循环连接（Nested Loop Join）](/ch3/#351-嵌套循环连接nested-loop-join)
      - [3.5.1.1 嵌套循环连接](/ch3/#3511-嵌套循环连接)
      - [3.5.1.2 物化嵌套循环连接](/ch3/#3512-物化嵌套循环连接)
      - [临时元组存储](/ch3/#临时元组存储)
      - [3.5.1.3 索引嵌套循环连接](/ch3/#3513-索引嵌套循环连接)
      - [3.5.1.4 其他变体](/ch3/#3514-其他变体)
    - [3.5.2 归并连接（Merge Join）](/ch3/#352-归并连接merge-join)
      - [3.5.2.1 归并连接](/ch3/#3521-归并连接)
      - [3.5.2.2 物化归并连接](/ch3/#3522-物化归并连接)
      - [3.5.2.3 其他变体](/ch3/#3523-其他变体)
    - [3.5.3 散列连接（Hash Join）](/ch3/#353-散列连接hash-join)
      - [3.5.3.1 内存散列连接](/ch3/#3531-内存散列连接)
      - [3.5.3.2 带倾斜的混合散列连接](/ch3/#3532-带倾斜的混合散列连接)
    - [3.5.4 连接访问路径与连接节点](/ch3/#354-连接访问路径与连接节点)
      - [3.5.4.1 连接访问路径](/ch3/#3541-连接访问路径)
      - [3.5.4.2 连接节点](/ch3/#3542-连接节点)
  - [3.6 创建多表查询计划树](/ch3/#36-创建多表查询计划树)
    - [3.6.1 预处理](/ch3/#361-预处理)
    - [3.6.2 获取代价最小的路径](/ch3/#362-获取代价最小的路径)
      - [基因查询优化器](/ch3/#基因查询优化器)
      - [3.6.2.1 第一层的处理](/ch3/#3621-第一层的处理)
      - [3.6.2.2 第二层的处理](/ch3/#3622-第二层的处理)
    - [3.6.3 获取三表查询代价最小的路径](/ch3/#363-获取三表查询代价最小的路径)
  - [参考文献](/ch3/#参考文献)
- [4 外部数据包装器与并行查询](/ch4/)
  - [4.1 外部数据包装器（FDW）](/ch4/#41-外部数据包装器fdw)
    - [Citus](/ch4/#citus)
    - [4.1.1 概述](/ch4/#411-概述)
      - [4.1.1.1 创建一棵查询树](/ch4/#4111-创建一棵查询树)
      - [4.1.1.2 连接至远程服务器](/ch4/#4112-连接至远程服务器)
      - [4.1.1.3 使用EXPLAIN命令创建计划树（可选）](/ch4/#4113-使用explain命令创建计划树可选)
      - [4.1.1.4 逆解析](/ch4/#4114-逆解析)
      - [4.1.1.5 发送SQL命令并接收结果](/ch4/#4115-发送sql命令并接收结果)
      - [postgres_fdw中远程事务的默认隔离级别](/ch4/#postgres_fdw中远程事务的默认隔离级别)
    - [4.1.2 postgres_fdw的工作原理](/ch4/#412-postgres_fdw的工作原理)
      - [PostgreSQL的FDW不会检测死锁](/ch4/#postgresql的fdw不会检测死锁)
      - [4.1.2.1 多表查询](/ch4/#4121-多表查询)
      - [4.1.2.2 排序操作](/ch4/#4122-排序操作)
      - [4.1.2.3 聚合函数](/ch4/#4123-聚合函数)
      - [下推](/ch4/#下推)
  - [4.2 并行查询](/ch4/#42-并行查询)
- [5 并发控制](/ch5/)
  - [PostgreSQL中的事务隔离等级](/ch5/#postgresql中的事务隔离等级)
  - [5.1 事务标识](/ch5/#51-事务标识)
  - [5.2 元组结构](/ch5/#52-元组结构)
  - [5.3 元组的增删改](/ch5/#53-元组的增删改)
    - [5.3.1 插入](/ch5/#531-插入)
      - [pageinspect](/ch5/#pageinspect)
    - [5.3.2 删除](/ch5/#532-删除)
    - [5.3.3 更新](/ch5/#533-更新)
    - [5.3.4 空闲空间映射](/ch5/#534-空闲空间映射)
      - [pg_freespacemap](/ch5/#pg_freespacemap)
  - [5.4 提交日志（clog）](/ch5/#54-提交日志clog)
    - [5.4.1 事务状态](/ch5/#541-事务状态)
    - [5.4.2 提交日志如何工作](/ch5/#542-提交日志如何工作)
    - [5.4.3 提交日志的维护](/ch5/#543-提交日志的维护)
  - [5.5 事务快照](/ch5/#55-事务快照)
    - [内置函数txid_current_snapshot及其文本表示](/ch5/#内置函数txid_current_snapshot及其文本表示)
  - [5.6 可见性检查规则](/ch5/#56-可见性检查规则)
    - [5.6.1 t_xmin的状态为ABORTED](/ch5/#561--t_xmin的状态为aborted)
    - [5.6.2 t_xmin的状态为IN_PROGRESS](/ch5/#562--t_xmin的状态为in_progress)
    - [5.6.3 t_xmin的状态为COMMITTED](/ch5/#563--t_xmin的状态为committed)
  - [5.7 可见性检查](/ch5/#57-可见性检查)
    - [5.7.1 可见性检查](/ch5/#571-可见性检查)
      - [提示位（Hint Bits）](/ch5/#提示位hint-bits)
    - [5.7.2 PostgreSQL可重复读等级中的幻读](/ch5/#572-postgresql可重复读等级中的幻读)
  - [5.8 防止丢失更新](/ch5/#58-防止丢失更新)
    - [5.8.1 并发UPDATE命令的行为](/ch5/#581-并发update命令的行为)
      - [伪代码：ExecUpdate](/ch5/#伪代码execupdate)
      - [以先更新者为准 / 以先提交者为准](/ch5/#以先更新者为准--以先提交者为准)
    - [5.8.2 例子](/ch5/#582-例子)
      - [例1](/ch5/#例1)
      - [例2](/ch5/#例2)
      - [例3](/ch5/#例3)
  - [5.9 可串行化快照隔离](/ch5/#59-可串行化快照隔离)
    - [5.9.1 SSI实现的基本策略](/ch5/#591-ssi实现的基本策略)
    - [5.9.2 PostgreSQL的SSI实现](/ch5/#592-postgresql的ssi实现)
      - [SIREAD锁](/ch5/#siread锁)
      - [读-写冲突](/ch5/#读-写冲突)
    - [5.9.3 SSI的原理](/ch5/#593-ssi的原理)
    - [5.9.4 假阳性的串行化异常](/ch5/#594-假阳性的串行化异常)
  - [5.10 所需的维护进程](/ch5/#510-所需的维护进程)
    - [5.10.1  冻结处理](/ch5/#5101--冻结处理)
  - [参考文献](/ch5/#参考文献)
- [6 清理过程](/ch6/)
  - [6.1 并发清理概述](/ch6/#61-并发清理概述)
    - [伪码：并发清理](/ch6/#伪码并发清理)
    - [6.1.1 第一部分](/ch6/#611-第一部分)
    - [6.1.2 第二部分](/ch6/#612-第二部分)
    - [6.1.3 第三部分](/ch6/#613-第三部分)
    - [6.1.4 后续处理](/ch6/#614-后续处理)
  - [6.2 可见性映射](/ch6/#62-可见性映射)
    - [6.2.1 可见性映射的改进](/ch6/#621-可见性映射的改进)
  - [6.3 冻结过程](/ch6/#63-冻结过程)
    - [6.3.1 惰性模式](/ch6/#631-惰性模式)
    - [6.3.2 迫切模式](/ch6/#632-迫切模式)
      - [如何显示pg_class.relfrozenxid与pg_database.datfrozenxid](/ch6/#如何显示pg_classrelfrozenxid与pg_databasedatfrozenxid)
      - [FREEZE选项](/ch6/#freeze选项)
    - [6.3.3 改进迫切模式中的冻结过程](/ch6/#633-改进迫切模式中的冻结过程)
  - [6.4 移除不必要的提交日志文件](/ch6/#64-移除不必要的提交日志文件)
    - [pg_database.datfrozenxid与clog文件](/ch6/#pg_databasedatfrozenxid与clog文件)
  - [6.5 自动清理守护进程](/ch6/#65-自动清理守护进程)
    - [关于如何维护AUTOVACUUM](/ch6/#关于如何维护autovacuum)
  - [6.6 完整清理（FULL VACUUM）](/ch6/#66-完整清理full-vacuum)
    - [伪代码：完整清理](/ch6/#伪代码完整清理)
    - [什么时候该使用VACUUM FULL？](/ch6/#什么时候该使用vacuum-full)
- [7 堆内元组与仅索引扫描](/ch7/)
  - [7.1 堆内元组（HOT）](/ch7/#71-堆内元组hot)
    - [7.1.1 没有HOT时的行更新](/ch7/#711-没有hot时的行更新)
    - [7.1.2 HOT如何工作](/ch7/#712-hot如何工作)
      - [HOT不可用的场景](/ch7/#hot不可用的场景)
  - [7.2 仅索引扫描](/ch7/#72-仅索引扫描)
  - [7.3 README.HOT](/ch7/#73-readmehot)
    - [堆内元组（HOT）](/ch7/#堆内元组hot)
    - [技术挑战](/ch7/#技术挑战)
    - [单个索引项的更新链](/ch7/#单个索引项的更新链)
    - [中止的情形](/ch7/#中止的情形)
    - [索引扫描与顺序扫描](/ch7/#索引扫描与顺序扫描)
    - [剪枝](/ch7/#剪枝)
    - [碎片整理](/ch7/#碎片整理)
    - [什么时候使用剪枝或碎片整理](/ch7/#什么时候使用剪枝或碎片整理)
    - [清理](/ch7/#清理)
    - [统计](/ch7/#统计)
    - [创建索引](/ch7/#创建索引)
    - [并行创建索引](/ch7/#并行创建索引)
    - [并行移除索引](/ch7/#并行移除索引)
    - [局限性](/ch7/#局限性)
    - [词汇表](/ch7/#词汇表)
- [8 缓冲区管理器](/ch8/)
  - [8.1 概览](/ch8/#81-概览)
    - [8.1.1 缓冲区管理器的结构](/ch8/#811-缓冲区管理器的结构)
    - [8.1.2 缓冲区标签（buffer_tag）](/ch8/#812-缓冲区标签buffer_tag)
    - [8.1.3 后端进程如何读取数据页](/ch8/#813-后端进程如何读取数据页)
    - [8.1.4 页面置换算法](/ch8/#814-页面置换算法)
    - [8.1.5 刷写脏页](/ch8/#815-刷写脏页)
      - [直接I/O（Direct I/O）](/ch8/#直接iodirect-io)
  - [8.2 缓冲区管理器的结构](/ch8/#82-缓冲区管理器的结构)
    - [8.2.1 缓冲表](/ch8/#821-缓冲表)
      - [散列函数](/ch8/#散列函数)
    - [8.2.2 缓冲区描述符](/ch8/#822-缓冲区描述符)
    - [8.2.3 缓冲区描述符层](/ch8/#823-缓冲区描述符层)
      - [为什么使用freelist来维护空描述符？](/ch8/#为什么使用freelist来维护空描述符)
    - [8.2.4 缓冲池](/ch8/#824-缓冲池)
  - [8.3 缓冲区管理器锁](/ch8/#83-缓冲区管理器锁)
    - [8.3.1 缓冲表锁](/ch8/#831-缓冲表锁)
    - [8.3.2 缓冲区描述符相关的锁](/ch8/#832-缓冲区描述符相关的锁)
      - [8.3.2.1 内容锁（content_lock）](/ch8/#8321-内容锁content_lock)
      - [8.3.2.2 IO进行锁（io_in_progress_lock）](/ch8/#8322-io进行锁io_in_progress_lock)
      - [8.3.2.3 自旋锁（spinlock）](/ch8/#8323-自旋锁spinlock)
      - [用原子操作替换缓冲区管理器的自旋锁](/ch8/#用原子操作替换缓冲区管理器的自旋锁)
  - [8.4 缓冲区管理器的工作原理](/ch8/#84-缓冲区管理器的工作原理)
    - [8.4.1 访问存储在缓冲池中的页面](/ch8/#841-访问存储在缓冲池中的页面)
    - [8.4.2 将页面从存储加载至空槽](/ch8/#842-将页面从存储加载至空槽)
    - [8.4.3 将页面从存储加载至受害者缓冲池槽中](/ch8/#843-将页面从存储加载至受害者缓冲池槽中)
    - [8.4.4 页面替换算法：时钟扫描](/ch8/#844-页面替换算法时钟扫描)
      - [伪代码：时钟扫描](/ch8/#伪代码时钟扫描)
  - [8.5 环形缓冲区](/ch8/#85-环形缓冲区)
    - [为什么批量读取和清理过程的默认环形缓冲区大小为256 KB？](/ch8/#为什么批量读取和清理过程的默认环形缓冲区大小为256-kb)
  - [8.6 脏页刷盘](/ch8/#86-脏页刷盘)
    - [为什么检查点进程与后台写入器相分离？](/ch8/#为什么检查点进程与后台写入器相分离)
- [9 预写式日志](/ch9/)
  - [9.1 概述](/ch9/#91-概述)
    - [9.1.1 没有WAL的插入操作](/ch9/#911-没有wal的插入操作)
    - [9.1.2 插入操作与数据库恢复](/ch9/#912-插入操作与数据库恢复)
    - [9.1.3 整页写入](/ch9/#913-整页写入)
  - [9.2 事务日志与WAL段文件](/ch9/#92-事务日志与wal段文件)
    - [WAL段文件尺寸](/ch9/#wal段文件尺寸)
    - [时间线标识](/ch9/#时间线标识)
    - [WAL文件名](/ch9/#wal文件名)
  - [9.3 WAL段文件的内部布局](/ch9/#93-wal段文件的内部布局)
  - [9.4 WAL记录的内部布局](/ch9/#94-wal记录的内部布局)
    - [9.4.1 WAL记录首部部分](/ch9/#941-wal记录首部部分)
    - [9.4.2 XLOG记录数据部分（9.4及以前）](/ch9/#942-xlog记录数据部分94及以前)
      - [9.4.2.1 备份区块](/ch9/#9421-备份区块)
      - [9.4.2.2 非备份区块](/ch9/#9422-非备份区块)
    - [9.4.3 XLOG记录数据部分（9.5及后续版本）](/ch9/#943-xlog记录数据部分95及后续版本)
      - [WAL压缩](/ch9/#wal压缩)
      - [9.4.3.1 备份区块](/ch9/#9431-备份区块)
      - [9.4.3.2 非备份区块](/ch9/#9432-非备份区块)
  - [9.5 WAL记录的写入](/ch9/#95-wal记录的写入)
  - [9.6 WAL写入进程](/ch9/#96-wal写入进程)
  - [9.7 PostgreSQL中的检查点过程](/ch9/#checkpoint-process)
    - [9.7.1 检查点过程概述](/ch9/#971-检查点过程概述)
    - [9.7.2 pg_control文件](/ch9/#972-pg_control文件)
    - [PostgreSQL 11中移除了前一个检查点](/ch9/#postgresql-11中移除了前一个检查点)
  - [9.8 PostgreSQL中的数据库恢复](/ch9/#98-postgresql中的数据库恢复)
  - [9.9 WAL段文件管理](/ch9/#99-wal段文件管理)
    - [9.9.1 WAL段切换](/ch9/#991-wal段切换)
    - [9.9.2 WAL段管理（9.5版及以后）](/ch9/#992-wal段管理95版及以后)
    - [9.9.3 WAL段管理（9.4版及以前）](/ch9/#993-wal段管理94版及以前)
  - [9.10 归档日志与持续归档](/ch9/#910-归档日志与持续归档)
- [10 基础备份与时间点恢复](/ch10/)
  - [10.1 基础备份](/ch10/#101-基础备份)
    - [10.1.1 pg_start_backup](/ch10/#1011-pg_start_backup)
      - [备份标签](/ch10/#备份标签)
    - [10.1.2 pg_stop_backup](/ch10/#1012-pg_stop_backup)
  - [10.2 时间点恢复（PITR）的工作原理](/ch10/#102-时间点恢复pitr的工作原理)
    - [ 为什么可以用一般归档工具做基础备份？](/ch10/#为什么可以用一般归档工具做基础备份)
  - [10.3 时间线与时间线历史文件](/ch10/#103-时间线与时间线历史文件)
    - [10.3.1 时间线标识（TimelineID）](/ch10/#1031-时间线标识timelineid)
    - [10.3.2 时间线历史文件](/ch10/#1032-时间线历史文件)
  - [10.4 时间点恢复与时间线历史文件](/ch10/#104-时间点恢复与时间线历史文件)
- [11 流复制](/ch11/)
  - [11.1 流复制的启动](/ch11/#111-流复制的启动)
    - [在备库长时间停机后，如果重启会发生什么？](/ch11/#在备库长时间停机后如果重启会发生什么)
  - [11.2 如何实施流复制](/ch11/#112-如何实施流复制)
    - [11.2.1 主从间的通信](/ch11/#1121-主从间的通信)
    - [11.2.2 发生故障时的行为](/ch11/#1122-发生故障时的行为)
  - [11.3 管理多个备库](/ch11/#113-管理多个备库)
    - [11.3.1 同步优先级与同步状态](/ch11/#1131-同步优先级与同步状态)
    - [11.3.2 主库如何管理多个备库](/ch11/#1132-主库如何管理多个备库)
    - [11.3.3 发生故障时的行为](/ch11/#1133-发生故障时的行为)
  - [11.4 备库的故障检测](/ch11/#114-备库的故障检测)
- [许可与授权](/license/)
  - [原著版权](/license/#原著版权)
  - [中文版与译本权利](/license/#中文版与译本权利)
  - [使用条款](/license/#使用条款)
  - [版本边界](/license/#版本边界)
  - [联系](/license/#联系)
