木匠钉子
Skip to content
博客

归档

按时间归档的所有文章。

2026

10 月 的文章,展开或收起
  1. 从索引命中到查询结果

    索引找到候选位置后,查询还要处理版本可见性、必要的条件复验和剩余过滤。从几份执行计划出发,看 Bitmap、Index Only Scan 和 GIN 怎样通过 AM 接口接上这些工作。

  2. 国产数据库,最后靠什么赢得信任?

    从一张感冒处方,想到国产数据库的信任问题:客户花的钱,到底买到了什么?

  3. B-tree 里的重复 Key 与旧记录的清理

    从一次阻止了 HOT 的普通 UPDATE 出发,解释 Unique Index 为什么允许重复 Key、B-tree 如何在插入路径上清理旧版本,以及 VACUUM 清理完成之后,空间为什么仍可能留在 Index 文件里。

  4. B-tree 的并发搜索与页面分裂

    一个 Backend 拿着过期的 Downlink 走进旧 Page,另一个刚好完成了 Split。High Key、Rightlink 以及 Incomplete Split,如何让这次并发搜索继续找到正确的 Key。

  5. Heap Page 里的旧版本,什么时候会被清理

    从一个 DELETE 留下的死元组出发,看它经过 Visibility Horizon、Page Pruning、LP_DEAD 和 Index Cleanup,最后能变成什么样;以及 VACUUM FULL 为什么要重新造一份 Heap。

9 月 的文章,展开或收起
  1. PostgreSQL 是怎么把 Tuple 写进 Heap 的

    顺着一次 Tuple 写入,看看 FSM、Visibility Map、Buffer Lock 和 WAL 是怎么在 Heap AM 里接到一起的。

  2. Checkpoint 调优,到底在调什么?

    Checkpoint 引起的 I/O 尖峰和延迟抖动,可能来自触发太频繁,也可能来自某一轮写得太重。把一次 Checkpoint 拆成 trigger、write、sync 三段,再顺着 WAL、pg_wal 和 Recovery 往下看,这几个参数各自管什么就清楚了。

  3. Checkpoint、BgWriter、WAL Writer,PG 的三个后台写进程

    Checkpointer、Background Writer 和 WAL Writer 都会在后台写盘,但它们守的是三个不同的边界:Recovery 从哪里开始、Buffer 能不能顺利复用、WAL 推进到了哪里。这三个边界之间,又一直在互相借力。

  4. WAL 已经可以相信了,Data Page 呢?

    COMMIT 返回时,被修改的 Data Page 往往还留在 Shared Buffers 里。WAL Flush 已经把 fsync 算进自己的语义,Data Page 却把 write 和 sync 拆成两步,中间还隔着一次责任交接。

  5. COMMIT 返回之前,PostgreSQL 到底在等什么?

    COMMIT 返回之前,PostgreSQL 要等 WAL 持久化到自己的 Commit LSN。可这条有序日志是一群并发 Backend 写出来的,这条线比想象中曲折。

8 月 的文章,展开或收起
  1. WAL 里面存的是 Page Diff 吗?

    一个 Page 在 Shared Buffers 里被修改以后,PostgreSQL 到底往 WAL 里留下了什么?从 Heap Insert 一路看到 B-tree Split、FPI 和 rmgr。

  2. 围棋、AI 与软件设计:真正重要的也许不是多算几步

    如果下棋只是比谁算得多,业余玩家是不是从一开始就输了?顺着这个疑问查了一圈,发现围棋要训练的,和做数据库设计要训练的,原来是同一件事。

  3. Shared Buffers 不是一个 Cache

    Shared Buffers 会缓存 Page,但沿着一个 Buffer Slot 的生命周期看下去,里面还有 identity、pin、I/O、dirty 和 eviction 组成的一整套协议。

  4. 一个 Backend 想睡一觉,为什么这么麻烦?

    条件不满足就睡,别人做完了再叫醒。听起来很简单,但并发系统最麻烦的地方,往往就藏在"决定要睡"和"真正睡下去"之间。

  5. 一个 Backend 是怎么进入 PostgreSQL“共享世界”的?

    有了 PID,为什么还要 PGPROC?有了 PGPROC,为什么还要 ProcArray?顺着 backend 的生命周期,看它怎么在共享内存里建立身份、发布状态,再安全退场。

7 月 的文章,展开或收起
  1. 事务都结束了,PostgreSQL 为什么还不能立刻释放锁?

    不是 PG 拖拖拉拉不想放锁,是放锁这件事本身就是在告诉其他人"我弄完了,你们可以进来了"。

  2. PostgreSQL 为什么宁愿重启,也不让共享内存随便长大?

    改个 shared_buffers 就要重启?不是不能动态扩,是不想为所有状态都背上在线迁移的债。

  3. Contributor 有什么了不起的?

    AI 能写 Patch,但能替我们成为贡献者吗?