You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL中SELECT FOR UPDATE关联表时更新外键不返回行的问题

PostgreSQL SELECT FOR UPDATE 关联表+更新外键时返回空行的问题

根据PostgreSQL显式锁文档中的描述:

SELECT FOR UPDATE会等待对同一行执行过相关命令的并发事务,之后会锁定并返回更新后的行(若行已删除则返回空)。

但实际场景中遇到了不符合预期的情况:当更新某行的外键字段,且SELECT语句关联另一张表时,SELECT FOR UPDATE并未返回更新后的行;更新其他字段时则符合文档描述。此时被并发事务更新外键的行似乎不可见,表现得如同被删除。

极简复现示例

预期两个并发事务都能更新该行,但实际只有一个能成功,第二个事务返回空。若将第一个事务的更新语句改为更新非外键字段,则两个事务都能正常查询到该行,符合文档描述。

注意:SELECT语句关联了foo表(该表未被更新),实际场景中需获取foo表字段;若不关联表,即使更新外键也能正常工作。触发该现象的两个关键条件为:

  1. 更新外键字段
  2. SELECT语句使用JOIN关联表
create table foo(pk int primary key);
create table bar(pk int, fk int references foo(pk), value int);
insert into foo values (1), (2), (3);
insert into bar values (1, 1, 1);

---- 第一个事务
begin;
select * from bar join foo on foo.pk = bar.fk where bar.pk = 1 for update of bar;
-- 此时并发执行第二个事务的SELECT语句,之后回到此处继续执行

update bar set fk = 2;
-- 若改为更新value字段,第二个事务将正常返回行
-- update bar set value = 10;
commit;


---- 第二个(并发)事务
begin;
select * from bar join foo on foo.pk = bar.fk where bar.pk = 1 for update of bar;
-- 继续执行第一个事务
-- 第一个事务提交后,此语句返回空;行未被锁定,无法更新
commit;

疑问

我在文档中遗漏了什么?该现象的原因是什么?希望能提供相关文档参考。

环境说明:该问题可在干净数据库中复现,无配置修改,使用Read Committed隔离级别。

内容的提问来源于stack exchange,提问作者Enkelli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:17:51