PostgreSQL的Read Committed隔离级别出现丢失更新的特殊场景是什么?
Read Committed隔离级别下的丢失更新场景与触发条件
典型场景:无锁并发更新操作
假设存在一个accounts账户表,结构如下:
CREATE TABLE accounts ( id INT PRIMARY KEY, balance NUMERIC(10,2) ); INSERT INTO accounts VALUES (1, 100.00);
两个并发事务(事务A、事务B)执行如下操作:
事务A执行流程
- 读取账户余额:
SELECT balance FROM accounts WHERE id = 1;(返回结果100.00) - 业务计算:余额增加50,得到150.00
- 模拟业务处理延迟(比如调用外部接口、复杂计算耗时)
- 执行更新:
UPDATE accounts SET balance = 150.00 WHERE id = 1;
事务B执行流程
- 在事务A读取余额后、更新前,读取同一账户余额:
SELECT balance FROM accounts WHERE id = 1;(同样返回100.00) - 业务计算:余额增加30,得到130.00
- 先于事务A完成更新:
UPDATE accounts SET balance = 130.00 WHERE id = 1; - 事务A完成延迟后执行更新,直接覆盖事务B的结果,最终账户余额为150.00(而非预期的180.00)
触发条件
- 数据库使用Read Committed隔离级别(PostgreSQL默认隔离级别)
- 并发事务采用「先读取数据、再基于读取结果更新」的操作模式,且读取操作未加排他锁(如
SELECT ... FOR UPDATE) - 后启动的事务先完成更新操作,导致先启动的事务基于旧数据的更新覆盖了前者的变更
引用《PostgreSQL 14 Internals》第52页Egor Rogov的描述:“但在某些情况下,Read Committed级别存在丢失变更的风险”
内容的提问来源于stack exchange,提问作者Dwayne Towell
相关产品推荐
相关产品推荐

