PostgreSQL不同隔离级别下并发更新同一行字段的处理逻辑
不同事务隔离级别下的更新冲突表现与回滚条件
场景说明
两个事务执行同一条更新语句,操作同一张表的同一条记录的同一字段,但设置不同的<value>:
update user set user.name = <value> where user.id = 1;
READ COMMITTED(读已提交)
执行表现
- 事务1先执行该更新语句,会立即给
user.id=1的记录加上排他锁(X锁),完成字段修改后暂不提交。 - 事务2执行相同语句时,尝试获取该记录的X锁,发现已被占用,会进入阻塞等待状态,直到事务1释放锁。
- 若事务1提交,事务2拿到锁后,会用自己的
<value>覆盖事务1提交的修改,之后可正常提交;若事务1回滚,事务2拿到锁后修改原始记录值,提交即可。
回滚触发条件
- 事务主动执行回滚操作(比如调用
ROLLBACK); - 事务在等待锁的过程中被强制中断(如锁等待超时、数据库服务重启);
- 执行更新时遇到异常(如磁盘空间不足、权限不足、记录被删除)。
REPEATABLE READ(可重复读)
执行表现
- 事务1执行更新后,同样对目标记录加X锁,未提交时,事务2执行更新会被阻塞,等待事务1释放锁。
- 与读已提交的核心差异体现在快照读的一致性(比如事务内多次查询同一条记录会看到相同结果),但本场景中都是更新操作(属于当前读),所以锁等待的执行流程和读已提交一致:事务1提交后,事务2覆盖修改;事务1回滚后,事务2修改原始值。
回滚触发条件
和READ COMMITTED完全一致,额外说明:可重复读级别下不会因“不可重复读”“幻读”这类一致性问题触发回滚,因为更新操作基于当前最新数据。
SERIALIZABLE(串行化)
执行表现
- 该级别下事务完全串行执行:事务1先执行更新并加X锁,未提交时,事务2执行更新会直接进入阻塞状态,直到事务1完成提交或回滚。
- 相较于前两个级别,串行化会给所有查询(包括普通SELECT)加锁,但本场景是更新操作,所以锁等待表现和前两者类似,本质是强制事务按顺序执行,彻底避免并发冲突。
回滚触发条件
- 与前两个级别相同的主动回滚、锁等待中断、执行异常;
- 注:本场景下两个事务仅操作同一条记录,不会出现死锁,若涉及多记录交叉锁才可能触发死锁回滚。
内容的提问来源于stack exchange,提问作者programmer
相关产品推荐
相关产品推荐

