PostgreSQL中使用UPDATE ... RETURNING原子追加JSONB数组时,并发更新是否会出现在返回行中?
PostgreSQL中使用UPDATE ... RETURNING原子追加JSONB数组时,并发更新是否会出现在返回行中?
放心,你的测试结果不是偶然——PostgreSQL绝对保证Request A的RETURNING结果只会包含它自己追加的缩略图,不会混入Request B的修改。下面结合你的场景拆解背后的机制:
行锁强制串行化写操作
当你执行这条UPDATE语句时:
UPDATE "Media" SET "Thumbnails" = "Thumbnails" || $1::jsonb WHERE "ContainerName" = $2 AND "BlobName" = $3 RETURNING *
PostgreSQL会在匹配到目标行的瞬间,获取排他行锁(Exclusive Row Lock)。这意味着:
- 如果Request A先到达,它会立刻锁定该行,Request B的
UPDATE会直接进入等待队列,完全无法对该行做任何修改,直到A的事务提交或回滚。 - 只有当A的事务结束、锁释放后,B的
UPDATE才会开始执行,此时它看到的是A修改后的行状态(也就是[thumb1]),再执行追加操作得到[thumb1, thumb2]。
RETURNING返回的是当前语句的修改结果
RETURNING子句的核心逻辑是:返回当前UPDATE语句执行完成后,该行的即时状态,这个状态完全由当前语句的修改决定,和其他并发事务无关:
- 对Request A来说,它的
UPDATE基于执行时看到的初始行快照([])进行追加,修改后得到[thumb1],RETURNING就返回这个结果——此时B还在等待锁,根本没机会触碰这行。 - 等A提交后,B的
UPDATE才会启动,基于A修改后的行版本继续操作,最终返回自己修改后的[thumb1, thumb2]。
结论:你的预期完全正确,且是PostgreSQL的硬性保证
你担心的“A的返回结果包含B的修改”是不可能发生的。PostgreSQL的行锁机制彻底隔离了并发写操作,确保每个UPDATE的修改都是串行执行的,RETURNING的结果必然是当前语句自己的修改产物,不会混入其他并发事务的变更。你的1000次并发测试结果,正是这个机制的必然体现,不是巧合。
备注:内容来源于stack exchange,提问作者Muhammed Furkan Güler
相关产品推荐
相关产品推荐

