Lobsters | 原文链接 | 2026-09-05 收录

在 Postgres 里插入状态迁移:追加式审计日志的并发竞态怎么解

来源: thoughtbot.com — 2026-08-24

概述

thoughtbot 的数据库设计续篇。上一篇他们用追加式的 user_statuses 表(只增不删)替代 users 表上的 status 列,以换取可高效查询的完整历史;这篇处理随之而来的边界情况:两个事务同一时刻改同一用户的状态会怎样?普通 status 列靠「最后一次写入胜出」由数据库天然串行化更新,覆盖虽静默但数据库层面不会出现矛盾态;而追加式模型两条记录都会存活,于是历史里出现了一条本不该发生的迁移——例如 Alice 一秒内既被批准又被驳回。作者指出,无论哪种设计,数据库本身都不会自动阻止并发迁移;对追加式方案而言,自然的解法是 SELECT ... FOR UPDATE 去锁住天然存在且每用户唯一的父行 users,让第二个事务等到第一个提交后再继续。若迁移伴随发邮件、调外部 API 等副作用,那并发下更要显式加锁,避免两边都触发。

核心要点

金句

Either way, neither approach prevents concurrent transitions on its own.(无论哪种方式,两种设计本身都无法阻止并发迁移的发生。)
返回 Lobsters 首页