丢失更新问题
两个用户加载同一行,修改不同字段,然后都保存。盲目的 UPDATE ... WHERE id = ? 写入最后的值,静默丢弃第一次修改。乐观并发让第二次写入显式失败。
UPDATE documents
SET title = $1, version = version + 1
WHERE id = $2 AND version = $3
RETURNING id, title, version;
如果返回零行,说明调用方的版本已过期。正确响应是重新加载、向用户展示冲突并重新应用变更,而不是用旧载荷重试。
何时使用
用于人工编辑的记录、配置对象和低竞争实体。与悲观锁相比,它避免在用户思考期间持锁。与可串行化隔离相比,它是应用层的定向检查,更容易按端点推理。
陷阱
版本列必须与数据原子更新。API 返回 409 Conflict 时应包含当前版本,让客户端重新加载。计数器应使用原子递增,而不是读-改-写。多行不变量不能只靠单行版本,应考虑使用可串行化隔离的事务。