土法炼钢兴趣小组的算法知识备份

【SQLite 内核】与 PG / InnoDB 机制对照:进程、WAL、锁、缓冲池

文章导航

分类入口
databasestorage
标签入口
#sqlite#postgresql#innodb#buffer-pool#wal#locking#process-model#comparison

目录

前 15 篇已经把 SQLite 的单文件、Pager、B-Tree、VDBE、Journal/WAL、锁与事务、计划器与备份走通。对读过 PostgreSQL 内核MySQL InnoDB 内核 的读者,下一个风险不是「不懂 SQLite」,而是把服务器行存的心智模型原样套过来:把 shared_buffers 当成 cache_size、把 PG 的 WAL 当成 SQLite 的 WAL、把行级锁经验拿去解释 SQLITE_BUSY

本文是系列第 16 篇,只做机制对照,不写选型决策树(留给 第 17 篇),也不写跨库吞吐排名。

  1. 用进程 / IPC、日志、锁、缓冲池四张表钉住差异与共同点。
  2. 标出「同名不同义」的陷阱词:WAL、snapshot、vacuum、buffer。
  3. 给出站内阅读对照路径:每一轴回链本系列与 PG/InnoDB 的对应篇。

本文是「SQLite 内核」系列第 16 篇(共 17 篇)。→ 系列目录

篇目 核心内容
第 15 篇 · 在线备份与 sqlite3_backup Backup API 与 cp 语义差
第 16 篇 · 与 PG / InnoDB 机制对照 进程、WAL、锁、缓冲池四轴
第 17 篇 · 选型与阅读地图 SQLite vs PG vs DuckDB vs RocksDB

版本锚定:本系列机制结论锚定 SQLite 3.45+ 官方文档与本机 3.53.2 实测路径;PostgreSQL / InnoDB 对照以站内已发布内核系列为准(PG 进程模型见 01-process-shmem;InnoDB 架构见 01-process-architecture)。本文引入未在本站或官方文档核对过的性能数字。


一、对照轴总图

flowchart LR
  subgraph sqlite ["SQLite embedded"]
    LIB["Library in app process"]
    FILE["One DB file + journal or WAL"]
    SW["Single writer per file"]
    LIB --> FILE
    LIB --> SW
  end
  subgraph server ["PG / InnoDB server"]
    PROC["Dedicated server processes or threads"]
    NET["Network protocol + auth"]
    MW["Multi-writer with row or page locks"]
    BUF["Shared buffer pool"]
    PROC --> NET
    PROC --> MW
    PROC --> BUF
  end
SQLite PostgreSQL InnoDB
部署形态 嵌入应用进程的库 独立 postmaster + backend mysqld 内存储引擎
数据载体 单文件(+ journal/WAL 附属) 多文件 / 表空间 表空间 / ibd
写并发 文件级单写者 多写者 + 行/元组锁 多写者 + 行锁 / gap
崩溃日志 rollback journal 或 SQLite WAL PG WAL + checkpoint redo / undo
缓存 每连接/进程 Page Cache shared_buffers 共享 Buffer Pool 共享

二、进程模型与 IPC

SQLite 删掉了「数据库服务器进程」这一层:调用是函数调用,不是 socket。代价是库与宿主同生共死——应用 OOM、被杀、错误地直接改 .db 文件,都会直接打到数据面(第 1、14 篇)。

PostgreSQL 用多进程 + 共享内存:每个连接一个 backend,缓冲池与锁表在共享段(postgresql-kernel/01)。InnoDB 跑在 mysqld 线程模型上,连接与存储引擎通过服务器层解耦(mysql-innodb/01)。

flowchart TB
  subgraph app ["Application"]
    A1["Business code"]
  end
  subgraph emb ["SQLite path"]
    A1 -->|"sqlite3_step"| VDBE
    VDBE --> Pager
    Pager --> File["db file"]
  end
  subgraph srv ["Server path"]
    A2["Client lib"] -->|"SQL over socket"| Backend
    Backend --> SharedBuf["Shared buffers"]
    SharedBuf --> Disk["Tablespace / files"]
  end

常见误解

  1. 「本机用 Unix socket 连 PG,延迟就和 SQLite 一类。」
    仍有协议编解码、backend 调度与共享缓冲池锁协作;零 IPC 是架构差,不是「本机部署」能抹平的。

  2. 「SQLite 没有并发,因为没有服务器。」
    多读者、WAL 下读写重叠、多连接都存在;缺的是多写者同时改同一文件(第 9–10 篇)。


三、日志:同名 WAL,不同契约

问题 SQLite WAL PostgreSQL WAL InnoDB redo
目的 单文件库的写前日志 + 读写重叠 崩溃恢复 + 复制基础 崩溃恢复
读者可见性 读者可读 WAL 帧 + 主文件快照 读缓冲池/页;复制另议 读 Buffer Pool;undo 可见性
提交点叙事 checkpoint 把帧合并回主文件 WAL flush + 事务提交记录 redo 落盘与事务提交协作
运维附属 -wal / -shm pg_wal 段文件 redo 日志组

本系列第 7–8 篇钉住:rollback journal 的提交点是「journal 不再 hot」;WAL 模式则反转读写关系。把 PG 的 checkpoint、归档、复制槽经验直接搬到 PRAGMA wal_checkpoint,会错位——SQLite 没有复制拓扑这一层。

InnoDB 的 redo/undo 与 SQLite journal 更接近「服务器级原子提交与 MVCC 版本」;对照时只借用「写前留恢复信息」这一共性,不假装参数可互换。


四、锁与隔离

SQLite 锁阶梯是文件级(UNLOCKED → SHARED → RESERVED → PENDING → EXCLUSIVE,第 9 篇);事务修饰词改变的是取锁时机(第 10 篇)。官方 isolation 叙事强调写串行化,而不是服务器式的多版本写写冲突检测。

PostgreSQL / InnoDB 提供行级(及更细)锁与丰富的隔离级别实现;站内 mvcc 与两套内核系列展开可见性、gap lock、SSI 等。可平移的只有词汇(脏读、幻读、write skew);不可平移的是「默认能撑多少并发写」。

场景 SQLite 常见现象 服务器行存常见现象
两写者抢同一库 SQLITE_BUSY / 等待 行锁等待或死锁检测
长只读 SHARED 可挡升 EXCLUSIVE(rollback);WAL 更友好 快照/VACUUM 交互另议
「SERIALIZABLE」标签 写串行化实现(官方 isolation) 实现路径因引擎而异

常见误解(续)

  1. 「把 BEGIN IMMEDIATE 当成 SERIALIZABLE 开关。」
    它提前拿 RESERVED,减少后来升锁失败;隔离叙事仍见第 10 篇与官方 Isolation In SQLite

  2. 「SQLite 的 snapshot 等于 PG 的 snapshot isolation。」
    WAL 读者看到的是一个检查点相关的稳定视图;没有多写者 SI 下的 write skew 戏台(第 10 篇)。


五、缓冲池与 Page Cache

SQLite Page Cache 服务本连接/本进程的页访问(第 3 篇);多进程打开同一文件时,靠 change counter 或 WAL-index 使缓存失效,而不是共享一块 shared_buffers

PostgreSQL shared_buffers 与 InnoDB Buffer Pool 是跨连接共享的服务器资源:命中率、刷脏、checkpoint 与服务器生命周期绑定。运维上「加大缓冲池」对 SQLite 的对应旋钮是 PRAGMA cache_size / 编译默认,且每个连接各自一份启发式缓存,不是集群级共享内存调参。

flowchart LR
  subgraph sqlcache ["SQLite"]
    C1["Connection A cache"]
    C2["Connection B cache"]
    F["Same db file"]
    C1 --> F
    C2 --> F
  end
  subgraph srvcache ["PG or InnoDB"]
    SB["Shared buffer pool"]
    TS["Tablespace"]
    B1["Backend 1"] --> SB
    B2["Backend 2"] --> SB
    SB --> TS
  end

六、站内对照阅读路径

你想对齐的问题 先读本系列 再读服务器系列
谁在跑、有没有 IPC 第 1、5 篇 PG 01-process-shmem;InnoDB 01
页与树 第 2–4 篇 PG/InnoDB 页面与索引章
日志与提交 第 7–8 篇 PG WAL 章;InnoDB Redo/Undo 章
锁与隔离 第 9–10 篇 mvcc + 两套锁章
缓存 第 3 篇 PG Buffer;InnoDB Buffer Pool
备份与损坏 第 14–15 篇 各系列备份/PITR 章(语义不同)

七、学术谱系、工程间隙与开放问题

谱系:三者都落在「页式存储 + 日志保证原子提交」的大传统上;SQLite 的分叉是嵌入式约束优先(Hipp 架构选择;Gaffney et al., PVLDB 2022 讨论其负载边界),PG/InnoDB 的分叉是多连接服务器与更细锁。B-Tree vs LSM 的另一条轴见 rocksdb 与本系列第 4、17 篇。

工程间隙:对照表描述的是机制角色,不是「谁更适合你的 QPS」。文件大小、写冲突率、是否需要网络多租户,会让同一机制轴上的优选翻转——这是第 17 篇的决策树,不是本篇能用一张表关闭的。

开放问题:嵌入式引擎是否应吸收更多服务器级细粒度锁,社区长期克制(第 1、9、10 篇);服务器引擎是否应提供「库级嵌入」形态(已有进程内扩展尝试,但不是本系列对象)。两边都没有「即将统一」的定论。

常见误解(收束)

  1. 「对照表可以当性能排名。」
    机制不同则 benchmark 口径不同;本站不做未实测的跨库排名。

八、小结

三句话小结

  1. SQLite 用嵌入式库 + 单文件 + 文件级单写者,删掉了 PG/InnoDB 的服务器进程、网络协议与共享缓冲池。
  2. WAL、snapshot、cache、vacuum 等词在三者中同名不同义;运维与排障经验必须换契约再复用。
  3. 四轴对照用于建立坐标系;何时选哪一类引擎,见第 17 篇决策树。

参考资料

官方与站内机制(A 级)

  1. SQLite ArchitectureWALLockingIsolation In SQLite
  2. 本系列第 1、3、7–10、14–15 篇。
  3. PostgreSQL 内核MySQL InnoDB 内核MVCC

论文(A 级)

  1. Berenson et al., SIGMOD 1995(隔离词汇)。
  2. Gaffney et al., SQLite: Past, Present, and Future, PVLDB 2022(嵌入式负载讨论框架)。

站内

  1. 本系列 indexPLAN.md选型与阅读地图

上一篇在线备份与 sqlite3_backup
下一篇选型与阅读地图

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-07-17 · database / storage

【SQLite 内核】Pager 与 Page Cache

拆解 Pager 作为 B-Tree 与操作系统文件之间的契约层:page cache 命中/未命中路径、脏页生命周期与提交前的可回滚保证,并与 PG shared_buffers、InnoDB Buffer Pool 的跨进程共享模型对照。

2026-07-18 · database / storage

【SQLite 内核】WAL 与 checkpoint:追加日志与读写并发

钉住 SQLite WAL 模式如何反转 rollback journal 的读写关系:原始内容留在主文件、新内容追加到 -wal,checkpoint 才把帧搬回主文件;用本机 3.53.2 实测 journal_mode=WAL 切换与 passive/truncate checkpoint 的真实帧数,读放大与 checkpoint 频率的取舍留作开放问题。


By .