今天读完 Designing Data-Intensive Applications 第七章
今天读完 Designing Data-Intensive Applications 第七章。感觉脑子被开过光。 第七章讲的是 Transactions(事务)。具体内容包括 ACID 的语义细节、weak isolation level 的几种实现(read committed、snapshot isolation、serializable)、以及 serializable snapshot isolation(SSI)这种相对新的算法。 这本书我读了第三遍,每次读这章都有新理解——可能是因为前两遍没有实际踩过相关的坑。第三遍读的时候,我已经在项目里写过「read-modify-write」逻辑、踩过 lost update、debug 过 phantom read。所以这次读,每个概念都有具体的代码段对应到脑子里。 「书读三遍其义自见」是真的。但前提是中间要有足够多的实际操练,否则三遍读的都是同一个空脑子。 具体说几个这次读才真正理解的点: snapshot isolation 的本质是 MVCC(多版本并发控制),每个事务开始时拿一个 txid,所有写都打到新版本,读只读 txid 之前的可见版本。这种方式避免了 read-write 阻塞,代价是版本累积需要定期 GC。 SSI(serializable snapshot isolation)的精髓是检测「dangerous structures」——也就是事务之间形成的读写依赖环。一旦检测到环,就 abort 其中一个事务,让应用重试。这种方式比传统的 2PL(两阶段锁)吞吐高很多,因为读不阻塞写、写不阻塞读。 MySQL InnoDB 的默认隔离级别是「repeatable read」(其实更接近 snapshot isolation 而不是标准定义的 RR),PostgreSQL 是「read committed」。这两个默认值在分布式场景下都容易出 bug——尤其是「lost update」问题,必须用 SELECT FOR UPDATE 或者乐观锁显式处理。 打算接下来把第八章(分布式系统的问题:故障、网络延迟、时钟)也读一遍。但这次会带着自己的 MyBlog 做实验——故意在 4321 端口的 web 服务和 8787 端口的 api 服务之间模拟一次网络分区,看 commentCount 的乐观锁到底能不能扛住。 DDIA 这本书最大的价值不是它告诉你「应该用哪个技术」,而是它告诉你「为什么这些技术会在这个特定历史时刻出现」。理解了 origin,理解 trade-off,做技术选型时才有判断力。 补充背景:DDIA 第一版是 Martin Kleppmann 在 2017 年出版的,到 2026 年仍然是分布式系统领域被引用最多的书之一。中文翻译第二版的 GitHub 仓库(Vonng/ddia)2026 年 4 月还在持续更新,包括补充贡献者链接和勘误。这本书的「长寿」本身就是对「技术书要追新」这个常见误区的反驳——基础理论的保质期比任何框架都长 10 倍。