Phil Eaton - databases

29 篇内容

技术文章Phil Eaton - databases

Writing a SQL database from scratch in Go: 1. SELECT, INSERT, CREATE and a REPL

本篇文章是“用 Go 从零写 SQL 数据库”系列的第一篇,目标是实现支持基本的 CREATE、INSERT、SELECT 命令和交互式 REPL 的最小数据库。作者从词法分析入手,设计 lexer 将输入转换为 token,依据 PostgreSQL 规则处理数字、字符串和标识符,并用 longestMatch 解决关键词前缀冲突;然后定义 AST 模型与递归下降解析器,分别解析三种语句。最后实现内存后端,用 map 存储表,以二进制表示 INT、字节串表示 TEXT,完成建表、插入和查询功能。文章给出完整代码与运行示例,并附测试,边界明确:仅支持单表基础操作,无持久化、事务和复杂表达式,适合初学者理解数据库与解析原理。

推荐收录,因为文章以可运行的 Go 代码完整展示了一个最小 SQL 数据库的词法分析、语法分析和内存执行流程,技术细节具体、步骤清晰,并配有测试样例与后续系列链接。适合想了解数据库内部机制、解析器实现或 Go 语言实践的中级读者,文中的 lexer/parser 组织方式和内存存储结构可直接迁移到其他小型解释器或教学项目。

技术文章Phil Eaton - databases

Writing a SQL database from scratch in Go: 2. binary expressions and WHERE filters

本文是《Writing a SQL database from scratch in Go》系列第二篇,在首篇基础上为 gosql 增加二进制表达式与 WHERE 过滤。作者扩展 AST 加入 binaryExpression,采用 Pratt parsing 处理运算符优先级和括号;重构内存后端,让每个表达式针对表行求值。求值器支持标识符、数字/字符串/布尔字面量以及算术、比较、逻辑等运算符,并明确不进行隐式类型转换。SELECT 语句新增 WHERE 条件逐行过滤,投影列可通过表达式计算,文中给出 REPL 交互示例。该实现目前只支持单表、简单运算符,并依赖内存存储,是教学性质的 SQL 引擎骨架,尚未涉及索引、连接等真实数据库特性。

推荐收录,因为文章完整展示了在 Go 中实现 SQL 解析与求值的过程,包含 Pratt 解析器、AST 设计、表达式求值和内存表数据流,且代码与解释同步。适合对数据库内核、编译原理或解释器实现感兴趣的读者,可作为手写 SQL 引擎的参考起点。其可迁移价值在于解析器优先级处理和行上下文求值框架可复用于其他小型语言或查询引擎,但需注意示例省略了类型强制转换、优化和持久化等生产特性。

技术文章Phil Eaton - databases

Writing a SQL database from scratch in Go: 3. indexes

文章在 gosql 项目中扩展索引支持,涵盖 PRIMARY KEY 词法解析、红黑树索引创建、插入时索引维护和 SELECT 查询优化。作者使用 GoLLRB 红黑树存储索引项,通过识别 WHERE 条件中可应用索引的模式,先用索引预筛选行再执行过滤。文章分析当前查询计划仅支持 AND 连接和列与字面量比较,不能合并范围条件,且索引并非总是优于线性扫描。基准测试显示 100 万行插入时带索引内存和耗时增加,但等值查询从秒级降至微秒级,体现空间换时间的权衡。

推荐收录,因为文章通过写一个 Go 语言 SQL 数据库的索引模块,完整展示主键约束解析、红黑树索引构建、插入维护和查询预筛选的端到端实现,并给出有/无索引的实测性能对比。适合想理解数据库索引原理、查询规划和存储引擎实现的读者;其简化取舍与限制分析也可作为进一步阅读真实数据库文档与源码的入门桥梁。

技术文章Phil Eaton - databases

Let's build a distributed Postgres proof of concept

本文通过约600行Go代码构建了一个分布式Postgres概念验证,解释了CockroachDB背后的核心组件:Postgres线协议、SQL解析、Raft共识和存储层。作者使用pgproto3、pg_query_go、Hashicorp Raft和bbolt,实现了CREATE TABLE、INSERT通过Raft复制到各节点,SELECT在任意节点本地执行。文章演示了多节点启动、通过HTTP手动加入集群、故障切换和重启后数据一致性。同时指出方案仅支持少量SQL、快照被禁用、日志重放效率低、JSON存储不高效,并且只实现了复制而非分片或跨分片事务。这个教程展示了如何将成熟库组合成可运行的分布式系统骨架,适合理解分布式数据库基础结构。

推荐收录,因为文章以可运行代码完整演示了分布式Postgres的核心机制:用Raft复制写操作、本地执行读操作,并明确说明了简化与局限。适合想理解CockroachDB等NewSQL系统底层组成或动手实现分布式数据库原型的读者。其将成熟库组合为可扩展骨架的思路、无快照设计取舍和故障切换验证过程具有可迁移价值,但需注意SQL支持和性能远非生产级。

技术文章Phil Eaton - databases

Extending gosql to supporting LIMIT and OFFSET

本文记录作者在 Go 实现的 SQL 数据库 gosql 中添加 LIMIT 和 OFFSET 支持的过程。作者首先更新词法分析器以识别两个新关键字,然后扩展 AST 结构并调整生成代码的辅助函数,使打印结果包含 LIMIT 和 OFFSET。接着,解析器在 SELECT 语句中识别这些子句并解析其后的表达式,同时将 LIMIT 和 OFFSET 作为 WHERE 表达式的边界分隔符。运行时内存后端会先计算 limit 和 offset 数值,然后在逐行过滤中跳过 offset 之前的行,并在超出 limit+offset 范围后停止。文章特别指出,LIMIT/OFFSET 仍需要扫描至少 offset 数量的行,不适合大数据集分页,应优先考虑基于索引的分页。该实现仅针对内存存储,未涉及其他后端或优化策略。

推荐收录,本文不是零散片段,而是完整展示了为 SQL 引擎添加 LIMIT/OFFSET 语法所需的词法、语法分析和运行时三个层次改动,并附有代码 diff 与运行验证。适合对数据库实现、编译前端或 Go 语言工程感兴趣的读者,其修改顺序和边界意识可迁移到类似扩展场景。风险是实现针对特定内存后端,未深入讨论一般化架构,但作为参考案例足够。

技术文章Phil Eaton - databases

Writing a document database from scratch in Go: Lucene-like filters and indexes

文章从零构建一个基于 Go 和 Pebble 的简易文档数据库,支持通过 HTTP 插入、按 ID 获取和搜索 JSON 文档,代码控制在 500 行以内。作者实现了一个简化版 Lucene 查询语言,包括带引号字段名/值、嵌套路径、相等和范围比较以及隐式 AND。为了加速等值查询,系统在独立索引库中存储“路径=值”到文档 ID 列表的映射,并在搜索时对多个等值条件取交集;基准测试显示 year=1918 的查询从约 1 秒降至 0.03 秒。文章明确指出现有实现不支持范围索引、全文搜索和数组字段,且索引存储采用逗号分隔的 ID 字符串,适合作为理解文档数据库基本原理的教学项目而非生产系统。

推荐收录:文章提供了可运行的 Go 实现,完整覆盖查询解析、路径求值、基于 Pebble 的存储和等值索引构建,并给出了索引前后的性能对比,具有清晰的动手教学价值。适合后端工程师、数据库初学者或希望理解 Lucene 风格查询和倒排索引简化模型的读者。可迁移价值在于展示如何用少量代码实现可扩展的键值查询与索引设计,同时明确标出范围查询、数组和全文搜索等未覆盖边界,避免误导。

技术文章Phil Eaton - databases

Writing a SQL database from scratch in Go: 4. a database/sql driver

文章是 Phil Eaton “从零用 Go 写 SQL 数据库”系列的第四篇,主题是让自制数据库 gosql 实现 Go 标准库 database/sql 驱动接口。作者展示了如何注册驱动、实现 Driver/Conn/Rows 等接口,以及如何将已有的解析、执行和结果处理逻辑封装到符合 database/sql 规范的 API 中。文中以具体代码说明 Open、Query、Next、Columns 等方法的实现要点,并明确指出当前版本不支持参数化查询、事务和预处理语句,仅处理第一条语句。最终通过一个使用标准 sql.Open 查询数据的示例验证了驱动的可用性。文章篇幅较短,重点在于解释接口契约与底层映射。

推荐收录,因为它以清晰代码展示了如何为自制数据库实现标准 database/sql 驱动,对理解 Go 数据库驱动接口的契约和低层数据流转有直接帮助。适合需要为自研存储系统提供标准 SQL 接入、或想学习 Go database/sql 内部机制的开发者。文章明确承认不支持参数化、事务和预处理,边界清楚,便于读者判断适用范围。

技术文章Phil Eaton - databases

Implementing the Raft distributed consensus protocol in Go

本文详细介绍用Go语言实现Raft分布式共识协议中领导者选举和日志复制两大核心组件,并构建其上分布式键值存储。作者从状态机与KV API入手,逐步实现持久化、RPC、选举超时、投票逻辑、日志复制与提交推进。文中强调按Raft论文图2建模状态,并给出二进制持久化优化、批量复制等工程取舍。实现约1000行,经过手动与压力测试,但未接入Jepsen,也未实现重配置和快照,且固定日志条目大小;作者明确声明不用于生产,仅用于学习。整体展示了从算法到可运行系统的完整路径,适合理解共识实现细节。

推荐收录,因为文章以完整Go代码和Raft论文为依据,系统讲解选举与日志复制,并明确给出测试情况与限制。适合想深入理解分布式共识实现、数据库复制或使用Raft库的工程师和研究者,可迁移用于实现类似协议或排查相关问题;主要风险是版本未经验证、缺少快照等生产特性。

技术文章Phil Eaton - databases

A minimal distributed key-value database with Hashicorp's Raft library

文章用单文件 Go 代码演示如何基于 Hashicorp Raft 库构建一个最小分布式键值数据库,约 260 行,通过 HTTP API 支持 set/get 和 join 操作。作者从 Raft 背景出发,逐步实现状态机(Apply、Restore、Snapshot 空实现)、节点初始化(BoltDB 日志存储、TCP 传输)和 HTTP 接口,其中 set 通过 Raft 日志复制,get 直接读本地内存但不保证强一致。文章最后给出可运行的完整示例,并提示未实现快照、不支持删除、节点需手动加入且仅用于学习。整体内容清晰展示了 Raft 库的集成流程与关键注意点,适合分布式系统入门参考。

推荐收录,因为文章以完整可运行的最小示例展示了 Hashicorp Raft 库的端到端集成路径,对理解 Raft 状态机、日志复制和集群管理具有直接帮助。适合分布式系统初学者或需要快速上手的开发者,其简洁实现可作为进一步实践和扩展的起点;同时文中明确指出了快照、读一致性和生产约束等简化点,避免了误用。

技术文章Phil Eaton - databases

How do databases execute expressions?

文章调查了 Cockroach、ClickHouse、DuckDB、PostgreSQL、SQLite、MySQL/MariaDB、MongoDB、TiDB 等系统如何执行查询表达式。作者通过阅读核心源码并以控制流函数为判断依据,区分了树遍历解释器、栈/寄存器虚拟机和 JIT 编译三类实现。结论显示多数数据库仍采用树遍历解释器,PostgreSQL 与 SQLite 使用虚拟机,MongoDB SBE 为栈式虚拟机,部分系统支持 JIT;ClickHouse、DuckDB、TiDB、Cockroach 还采用向量化执行。文章认为向量化和 JIT 更契合列存分析负载,事务系统迁移到编译器架构的收益未必显著;局限是结论来自源码阅读,可能存在误判且缺少性能基准。

本文通过大量数据库源码调查,给出了表达式执行模型的一手判断,具有长期技术索引价值。适合数据库内核开发者、查询引擎研究者以及想理解解释器与虚拟机差异的读者。其源码判断方法可直接迁移到其他系统,但需注意结论为静态阅读而非基准验证。

技术文章Phil Eaton - databases

Exploring PL/pgSQL part two: implementing a Forth-like interpreter

文章详细展示了如何在 PostgreSQL 的 PL/pgSQL 中从头实现一个类似 Forth 的栈式解释器。作者首先介绍 Forth 语言的基本概念,然后逐步实现数据栈、程序计数器、条件分支(IF/THEN)、内建指令(DUP、SWAP、算术运算等)以及函数定义(DEF)和调用(CALL)机制,并通过 hstore 扩展存储函数入口位置,使用返回指针栈处理嵌套调用。最终通过运行递归斐波那契函数验证了解释器的正确性。文章还指出了实现中的一些 PL/pgSQL 特性限制,如数组长度处理、NULL hstore 合并等问题。该实现仅为 Forth 的子集,未涉及完整 Forth 的诸多特性,但足以展示在受限的数据库过程语言中构造解释器的可行方法。

推荐收录,因为文章提供了一个完整可运行的 PL/pgSQL 解释器实现,包含逐步代码解释、设计取舍和实际运行验证,不是简单的语法介绍或新闻转述。适合对 PostgreSQL 内部过程语言、解释器构造或栈机器实现感兴趣的读者。其可迁移价值在于展示了在资源受限且语法特殊的嵌入式语言中实现编程语言核心机制的方法,对理解解释器原理和数据库编程均有启发,技术主题长期有效。

技术文章Phil Eaton - databases

A minimal RocksDB example with Zig

本文介绍用 Zig 编写一个最小 RocksDB 嵌入式键值数据库示例,封装 C API 实现 set、get 和基于前缀的 list 命令。作者先说明 RocksDB 以 C++ 编写但提供 C API,便于其他语言集成;随后逐步展示如何在 Zig 中用 @cImport 导入头文件,定义 RocksDB 包装结构,并调用 rocksdb_open、put、get 及迭代器接口。文中重点解释了 Zig 的类型系统和互操作细节,包括 error 类型缺陷、可选指针、C 字符串到切片的转换,以及匿名结构体在跨函数返回时的类型不兼容问题。最后给出 Linux 上的编译步骤、build.zig 配置和命令行运行结果。该示例仅适用于 Linux 与 Zig 0.10.x,RocksDB C API 文档不足,需参考头文件和测试代码。

文章提供了完整可运行的 Zig 调用 RocksDB C API 的最小示例,系统解释了 Zig 的错误处理、可选指针、C 字符串转换及构建配置,直接证据充分。适合希望学习系统编程语言与 C/C++ 库互操作、或集成嵌入式 KV 存储的开发者。可迁移价值在于 FFI 模式和 RocksDB 基础用法,但需注意 Zig 版本(0.10)与当前版本存在差异。

工程实践Phil Eaton - databases

Writing a minimal in-memory storage engine for MySQL/MariaDB

文章记录了作者在一周黑客活动中探索 MariaDB 内部机制并实现一个 218 行 C++ 的最小内存存储引擎的全过程。作者从构建调试版 MariaDB 开始,发现存储引擎插件必须放在源码树内而非独立仓,并实现了 handler 子类的 create、write_row、rnd_next、rnd_init 等关键方法。文中解释了 MySQL 的固定字节行格式和全局内存表结构,同时坦诚该引擎仅支持 INTEGER 字段、单数据库、非线程安全且不支持 NULL。作者还将 MySQL 与 Postgres 的存储引擎 API 进行对比,认为基于单行传递的设计限制了列存压缩和向量化的收益。最终通过 SQL 查询验证了引擎功能,并指出这类最小项目可作为探索其他存储后端的起点,适合作为学习数据库存储层原理的入门材料。

本文是难得的数据库存储引擎实战教程,作者以最小可行方式展示了如何从零接入 MariaDB 存储接口,代码完整且步骤清晰,并诚实标注了线程安全、数据类型等局限。适合对数据库内核、存储引擎或后端系统感兴趣的开发者阅读,可迁移价值在于理解存储引擎接口的设计约束以及如何快速验证自定义存储方案,同时避免被过度简化的示例误导。

工程实践Phil Eaton - databases

Go database driver overhead on insert-heavy workloads

文章针对 Go 语言中插入密集型数据库工作负载,对比 SQLite 和 PostgreSQL 的流行驱动与替代驱动的性能。作者使用统一基准:1000 万行、两种列数和数据大小,每个测试运行 10 次,记录中位数、标准差、最小/最大和吞吐量。结果表明,最流行的 SQLite 驱动 mattn/go-sqlite3 比作者维护的 gosqlite 慢约 20-40%;PostgreSQL 的 lib/pq 比 pgx(绕过 database/sql)慢约 44-76%,且 lib/pq 已停止开发。作者推测 database/sql 接口可能是开销来源之一,但未完全证明。对于小结果集查询,驱动间差异不大。结论是建议 Go 开发者在插入密集型场景中自行基准测试驱动,并优先考虑 pgx。

推荐收录,因为文章提供了可复现的、具体数据支撑的驱动性能对比,直接指导 Go 开发者在批量插入场景下的技术选型。文章不仅给出结论,还公开了基准测试方法和代码仓库,便于读者验证和扩展。适合后端工程师、数据库应用开发者参考,可迁移价值在于提醒性能敏感场景避免盲从默认驱动,且需关注 database/sql 接口的潜在开销。

技术文章Phil Eaton - databases

Writing a SQL database, take two: Zig and RocksDB

文章展示了如何在 Zig 语言中用约 1700 行代码实现一个基于 RocksDB 的嵌入式 SQL 数据库。作者将项目拆分为词法分析、语法分析、存储层和执行层,详细讲解了每个组件的设计,包括手写 lexer/parser 支持 SELECT、INSERT、CREATE TABLE 等语句,以及如何用 RocksDB 持久化表元数据和行数据。文中还介绍了 Zig 的内存管理(Arena allocator)、数据序列化方案和表达式求值。该实现仅支持极小的 SQL 子集,无主键、事务和索引,主要用于学习数据库内部原理和 Zig/RocksDB 的实践,而非生产用途。

推荐收录,因为文章提供了完整可运行的代码实现和逐步讲解,清晰展示了从 SQL 解析到键值存储映射的完整流程。适合对数据库内部实现、Zig 语言或 RocksDB 感兴趣的开发者阅读,可迁移价值在于理解手写 lexer/parser 的实践、内存管理策略以及嵌入式数据库的架构设计。主要风险是项目功能有限,但作为教学参考具有长期价值。

工程实践Phil Eaton - databases

Intercepting and modifying Linux system calls with ptrace

文章介绍在amd64/Linux上使用ptrace拦截并修改系统调用,用Zig实现故障注入器,通过fork子进程、PTRACE_TRACEME和PTRACE_SYSCALL在系统调用入口与出口暂停。作者实现sys_write钩子:入口处把rdx写入长度截断2字节模拟短写;出口处将rax改为-EIO,从而绕过Go、Python、C内置write对EAGAIN的重试。文中还展示了用PTRACE_GETREGS/SETREGS操作寄存器,以及用PTRACE_PEEKDATA读取子进程内存打印写入内容。最终成功触发短写,并讨论方案局限:仅覆盖amd64/Linux、存在性能开销,未来可结合seccomp过滤优化。

推荐收录,因为文章用可运行的Zig代码完整演示了ptrace拦截系统调用的入口与出口、寄存器修改和内存读取,并通过真实调试发现Go/Python/C内置write对EAGAIN的重试行为,最终用返回EIO成功触发短写故障。适合从事Linux系统调试、故障注入和可靠性测试的工程师,方法可迁移到其他系统调用和语言,但需注意其仅覆盖amd64/Linux且ptrace存在性能开销。

个人心得Phil Eaton - databases

A paper reading club at work; databases and distributed systems research

文章记录了作者在公司内发起数据库与分布式系统论文阅读俱乐部的亲身经历。他为了避免过频或过疏,将讨论频率定为每两周一次,并选择异步邮件作为主要交流方式,理由是邮件更适合全球团队、更慢、不易错过且易于管理。作者先在通用频道小范围征集兴趣,一天内获得6人响应,随后扩展到29人,覆盖产品、支持、开发等多个角色。他还回顾了大学研究实习期间参加论文阅读会的经历,希望在工作环境中重现这种学术氛围。文章定位为他人提供一份可复制的蓝图,重点在于组织流程而非技术深度,适合希望建立团队学习机制或培养论文阅读习惯的读者。

推荐收录,因为它提供了在公司发起论文阅读俱乐部的具体操作步骤和背后考量,特别是异步邮件讨论和两周一次频率的选择理由。文章适合技术团队管理者、学习小组组织者或希望建立稳定论文阅读习惯的个人,其可迁移价值在于低成本的启动方法、跨时区协作策略以及从个人兴趣扩散为团队活动的路径。需要注意的是文章偏重组织经验,技术深度有限,更适合作为实践参考而非论文内容解读。

技术文章Phil Eaton - databases

What's the big deal about key-value databases like FoundationDB and RocksDB?

文章系统介绍键值数据库(嵌入式如 RocksDB、LevelDB、PebbleDB,分布式如 FoundationDB、TiKV)在当代数据库系统中的重要性。作者从数据库可扩展性切入,解释存储引擎可替换如何帮助优化分析型或写密集型负载,并详细说明将 SQL 行映射为键值对的具体编码方法,包括表标识、主键和行标识组合及高效前缀扫描。文章梳理了可靠存储、嵌入式部署、高效前缀扫描等关键特性,并列举构建在这些存储上的多种数据库实例。最后区分了嵌入式与分布式键值数据库的架构差异,并指出非数据库开发者或非大规模场景可忽略存储层细节。

推荐收录,因为文章清晰梳理了键值存储在现代数据库架构中的核心作用,提供了 SQL 到 KV 映射的具体思路和真实数据库案例,适合想理解数据库存储层或构建数据库系统的开发者。它作为入门导览具有较好的长期参考价值,能帮助读者建立对存储引擎选型和架构分层的整体认知。

技术文章Phil Eaton - databases

Exploring PL/pgSQL: Strings, arrays, recursion, and parsing JSON

本文是一篇面向 PL/pgSQL 初学者的实践教程,从基础函数定义、命名参数、OUT 参数和递归函数入手,逐步过渡到字符串与数组操作、自定义复合类型,最终实现一个能解析 JSON 对象子集的词法分析器和语法解析器。作者强调目标不是生产级代码,而是熟悉语言特性,因此明确排除了嵌套对象、数组、Unicode 和小数等复杂场景。文中给出了完整可运行代码、测试脚本和错误处理示例,展示了如何利用 PL/pgSQL 的内置 SQL 函数、数组操作和自定义类型完成命令式编程任务。

推荐收录,因为文章不是简单罗列语法,而是通过实现字符串转数组、递归斐波那契和 JSON 解析器三个递进式例子,让读者理解 PL/pgSQL 的函数声明、控制流、复合类型和错误处理机制。对需要在 PostgreSQL 中编写存储过程、触发器或复杂业务逻辑的开发者来说,文中的代码模式和调试方法具有直接参考价值,且作者对语言边界和适用场景的说明清晰克制。

个人心得Phil Eaton - databases

First month on a database team

作者记录了自己加入 EnterpriseDB 分布式 Postgres 团队第一个月的 onboarding 经验。他提出先避开困难的人员、组织与流程问题,利用初期 sprint 自由度专注于构建、测试、运行和文档等可独立完成的任务。具体策略包括收集构建过程写内部博客,尝试静态/动态分析,探索测试覆盖率受阻后转向学习测试框架并撰写测试指南,将 quickstart 迁移到集成测试框架,编写启动本地集群的脚本,以及通过阅读文档和提出“笨问题”加深理解。他还建议将个人笔记开放为团队文档,并尝试绘制架构图。文章强调精确记录必要步骤与试错路径、公开分享学习成果、以及在团队频道中提问的价值。该方法适用于开发者快速上手复杂系统,但主要提供个人经验,尚未涉及深层技术细节。

推荐收录:作者以数据库团队新人视角,清晰展示了从构建、测试到文档的系统性 onboarding 路径,并提供了具体可操作的做法,如写内部博客沉淀知识、将 quickstart 移植为测试、用“笨问题”推动团队理解。适合即将加入新团队或需要快速熟悉复杂代码库的工程师,其方法可迁移到其他基础设施或后端项目。主要风险是内容偏个人经验,技术细节有限,但作为职业成长与工程实践反思仍具长期参考价值。

技术文章Phil Eaton - databases

Exploring a Postgres query plan

文章记录作者在探索 Postgres 查询执行钩子时的学习过程,目标是从 QueryDesc 计划对象重建原始 SQL 字符串。作者搭建了带共享库的调试环境,通过 ExecutorRun_hook 拦截查询,并逐步解释 Plan 节点、范围表、OpExpr、Const、Var 等关键结构。文中给出完整 C 扩展代码,示范如何查找关系名、操作符名和列名。最终实现对简单 SELECT 的 SQL 重建,验证了 a > 1、a + 1 和常数比较等场景。该方法仅覆盖顺序扫描、整型常量与基础 Vars,尚未处理连接、聚合、子查询和别名等复杂计划,且依赖特定版本 Postgres 内部 API。

推荐收录,因为这是一篇可复现的数据库内核级工程笔记,而非泛泛介绍:作者提供了完整 hook 代码、构建方式,并逐步验证从计划树重建 SQL 的能力。适合数据库内核、Postgres 扩展开发者以及对查询计划内部表示感兴趣的后端工程师。其可迁移价值在于展示如何遍历计划节点、解析表达式并访问系统目录,但注意依赖特定版本内部 API,升级时可能变化。

技术文章Phil Eaton - databases

Writing a storage engine for Postgres: an in-memory Table Access Method

文章围绕Postgres 12引入的可插拔表访问方法(Table Access Method)API,通过实现一个内存存储引擎原型系统介绍了其工作机制。作者从Postgres调试构建和扩展基础设施开始,逐步探索TableAmRoutine结构体中必需的回调函数,通过日志和断言定位到slot_callbacks、scan_begin、getnextslot等关键方法。文章详细记录了如何在C扩展中管理表结构、存储行数据、处理插入和扫描,并解决slot填充、扫描状态管理等实际问题。最终原型支持创建内存表、插入整数和执行简单SQL查询,展示了复用Postgres上层SQL、协议和生态的潜力。作者明确说明这是原型质量代码,尚未实现索引、删除、更新等完整功能,适合作为进一步探索的基础。

推荐收录,因为文章填补了Postgres表访问方法缺乏最小实现教程的空白,以逐层调试和可运行代码展示了从扩展骨架到内存存储引擎的完整过程。适合数据库内核开发者、Postgres扩展作者和想理解可插拔存储引擎的读者,文中的调试方法、API使用陷阱和原型边界具有直接参考价值。

技术文章Phil Eaton - databases

An intuition for distributed consensus in OLTP systems

文章旨在建立对OLTP系统中分布式共识(尤其是Raft算法)的直觉。作者先解释Raft的基本机制:领导者选举、日志复制、提交和跟随者追赶,然后阐明分布式共识通过副本提供高可用和线性一致性,同时强调其本身并不提供水平扩展,水平扩展需通过分片实现。文章讨论了添加节点对延迟和可用性的权衡,并列举了实际优化技术,包括快照、批处理、磁盘/网络优化和灵活法定人数。此外还涉及安全与测试方法,如Jepsen、确定性测试和TLA+规格验证。最后指出共识开销大,应根据一致性需求选择合适方案。文章主要适用于OLTP系统,未深入非OLTP共识算法或具体实现细节。

推荐收录,因为文章用简洁直观的方式梳理了Raft在OLTP系统中的运作机制,并纠正了分布式共识常被误解为水平扩展的问题。作者从线性一致性、可用性、节点扩展、优化和测试等多个角度展开,既有理论直觉也有工程实践视角,适合分布式系统初学者和数据库工程师建立基础框架,同时为进阶读者提供了丰富的进一步阅读线索。

技术文章Phil Eaton - databases

A write-ahead log is not a universal part of durability

文章围绕持久性与预写日志(WAL)展开,作者通过伪代码逐步演示:内存数据库先写全量 B 树到磁盘并 fsync,虽然可实现持久性但效率很低;随后引入 group commit 摊销 fsync 成本,但每次仍写全量结构。作者指出更优做法是先写客户端请求到只追加日志并 fsync,即可安全返回,主数据结构延迟写入,启动时重放日志,这就是 WAL。文章还讨论了 fsync 失败处理、磁盘/文件系统损坏时 checksum 的作用、CDC 与 WAL 的关系,并强调多数数据库默认配置在安全与性能间权衡。最后总结持久性首先取决于向客户端返回成功前是否已落盘,WAL 是低成本实现手段。文章以浅显代码示例搭建直觉,适合理解存储持久性机制,但不涉及具体数据库生产实现细节。

推荐收录,因为文章以清晰的伪代码推演解释了 WAL 并非持久性唯一手段,而是针对全量写盘低效的优化方案。它把 fsync、group commit、checksum 和日志重放等概念串联起来,有助于读者建立数据库持久性的正确心智模型。适合后端工程师、数据库学习者和对存储系统感兴趣的人阅读。需要注意的是,文中为教学目的做了简化,不能直接等同于生产级实现。

技术文章Phil Eaton - databases

Implementing MVCC and major SQL transaction isolation levels

文章用约 400 行 Go 代码实现了一个内存键值数据库,并基于 MVCC 和乐观并发控制支持五种 SQL 事务隔离级别:读未提交、读已提交、可重复读、快照隔离和可串行化。作者从多版本数据结构和可见性规则开始,逐步实现不同隔离级别下的读写逻辑,并通过读写集合在提交时进行写-写冲突或读-写冲突检测。文中用带注释的测试展示并发事务行为差异,同时讨论真空清理、版本存储放大等现实约束,并指出教学实现的局限,如未处理范围查询、子事务和保存点。

推荐收录,因为它以可运行的最小实现和测试清晰地解释了数据库事务隔离级别的核心机制,而非停留在概念罗列。适合数据库初学者、后端工程师或需要理解事务可见性和并发异常的读者;文中展示的版本可见性规则和冲突检测思路可以迁移到实际数据库选型与事务调试中。主要局限是教学简化,未覆盖生产级范围查询等细节。

技术文章Phil Eaton - databases

Build a serverless ACID database with this one neat trick (atomic PutIfAbsent)

文章以 Delta Lake 论文和协议为蓝本,用约 500 行 Go 零依赖代码实现了一个受 Delta Lake 启发的 serverless ACID 数据库。核心是利用对象存储的原子 putIfAbsent 语义,通过不可变数据文件和带事务 ID 的元数据日志实现快照隔离。文中详细演示了基于 POSIX link 的文件系统原子写入、事务动作、内存行缓冲、数据对象刷新和扫描迭代器,并用两个并发测试验证写冲突与读快照行为。作者明确指出该实现仅支持建表、插入和全表扫描,未覆盖更新、删除、日志 checkpoint、压实等,且合并所有表的事务日志比 Delta Lake 更严格,带来更高写冲突。

推荐收录,因为文章不是泛泛介绍,而是给出了从对象存储原语到事务提交的完整可运行实现,并通过测试展示了并发读写的实际行为。适合想理解 Delta Lake、Iceberg 类事务机制或实现对象存储上最小 ACID 数据库的读者,其抽象接口和原子提交思路可直接迁移到教学或原型系统。主要边界是省略了更新删除等生产特性,单写者模型也限制了并发写能力。

技术文章Phil Eaton - databases

Transactions are a protocol

文章提出事务并非存储系统的固有属性,而是一种可以在任意存储系统上实现的协议。作者引用 Delta Lake、Orleans 在云存储上实现事务,以及 Epoxy 在 Redis 等系统上提供事务的方案,并提到两阶段提交作为经典例子。文章进一步指出,即使 PostgreSQL、MySQL、SQLite 已内置事务,开发者也可以选择绕开并实现自己的事务层,如 Convex 所做。作者认为,在需要一致性、原子性和隔离性,尤其是跨数据系统构建应用时,应把事务协议视为系统设计工具箱中的一种工具。文章以观点阐述和文献导引为主,未深入实现细节与性能评估。

这篇短文以清晰的视角将事务定义为可移植协议,串联了多个数据库系统的实现案例,适合需要理解跨存储系统一致性或设计事务层的读者。其价值在于提供思维框架和进一步阅读线索,但内容较为概略,应作为入门索引而非实现参考。

技术文章Phil Eaton - databases

Things that go wrong with disk IO

本文围绕磁盘 I/O 中可能导致数据丢失或损坏的场景展开,涵盖写入未达磁盘、fsync 失败、数据损坏、部分写入、假写、误写/误读等。作者基于 Parity Lost and Parity Regained 与 Characteristics, Impact, and Tolerance of Partial Disk Failures 两篇论文,解释了 buffered I/O 下 fsync 的必要性及其不可靠性,并介绍校验和、原子写、O_DIRECT 等缓解措施。文中对比了 Postgres、SQLite、MySQL、MongoDB、RocksDB 等系统在持久化、校验和与撕裂写处理上的默认行为,指出部分系统默认开启校验和,部分未开启,且假写和误写/误读常被忽视。文章限定于 Linux 环境,强调不同文件系统与磁盘的扇区大小差异,适合需要理解存储可靠性边界的开发者和数据库工程师。

本文以具体故障场景为线索,结合真实数据库系统的默认行为,清晰解释了磁盘 I/O 中容易被忽视的可靠性问题,如 fsync 失败、撕裂写和假写。适合需要设计或维护持久化系统的工程师,尤其是数据库与存储系统开发者。其价值在于将零散的 I/O 风险系统化,帮助读者在事务性场景中做出更稳妥的 fsync、校验和与原子写决策。

技术文章Phil Eaton - databases

What's the big deal about Deterministic Simulation Testing?

文章系统介绍确定性仿真测试(DST)的核心思想:将分布式系统的多个节点运行在单线程中,通过注入受控的随机种子与时钟来消除非确定性,并在模拟中注入磁盘、网络和进程故障。作者用伪代码演示如何改造退避重试、文件读取和分布式节点等代码,说明需将随机源与时间依赖参数化,并限制为异步 IO。文章还讨论了实现中的非确定性来源、工作负载设计与模拟边界,指出 DST 并非万能,种子可复现性受代码变更影响。最后对比 Jepsen,强调 DST 虽不能替代生产验证,但能显著提高系统核心稳定性。

推荐收录,因为文章用具体伪代码和真实案例(FoundationDB、TigerBeetle、Antithesis 等)清晰解释了 DST 的原理、实现约束与局限性,不是泛泛而谈。适合分布式系统、后端和测试工程师理解如何通过受控随机与故障注入提高系统可靠性,同时避免对 DST 产生不切实际的期望。