在PostgreSQL中,使用UPDATE ... RETURNING对 JSONB数组进行原子追加时,返回的行中会包含并发更新吗?

后端开发 2026-07-12

我在PostgreSQL的 jsonb 数组列上实现原子追加操作,并希望理解 UPDATE ... RETURNING 的并发行为。

我的表包含:

"Thumbnails" jsonb NOT NULL DEFAULT '[]'::jsonb

示例内容:

[
  {"Url": "thumb1"},
  {"Url": "thumb2"}
]

我将添加一个新的缩略图,方案是:

UPDATE "Media"
SET "Thumbnails" = "Thumbnails" || $1::jsonb
WHERE "ContainerName" = $2 AND "BlobName" = $3
RETURNING *

其中 $1 是一个JSON对象,例如:

{"Url":"thumb3"}

这是通过EF Core使用 FromSqlInterpolated 调用的,返回的行会映射回实体。

设想有两个请求几乎同时运行:

请求A:追加 {"Url":"thumb1"}
请求B:追加 {"Url":"thumb2"}

我预计PostgreSQL的行级锁会把它们串行化:

  1. A获得行锁
  2. A将 [] 更新为 [thumb1]
  3. A返回 [thumb1]
  4. B等待
  5. B将 [thumb1] 更新为 [thumb1, thumb2]
  6. B返回 [thumb1, thumb2]

我的主要问题:

是否有可能请求A 的 RETURNING 结果已经包含请求B 附加的缩略图(例如 [thumb1, thumb2])?

换言之,RETURNING 是否总是反映紧随该条语句之后的行状态,还是可能包含在执行期间提交的另一事务所作的更改?

我对大约1000个并发请求进行了压力测试,第一条请求始终只返回它自己的缩略图。我想知道这是否是PostgreSQL的保证,还是仅仅由时序引起的结果。

解决方案

答案取决于所使用的 事务隔离级别

  • 如果你使用的是默认的隔离级别 READ COMMITTED,PostgreSQL的行为将完全符合你的预期:第二个事务将在第一个提交前被阻塞,并且它将看到该行处于第一个事务所放入的状态。
  • 如果你使用更高的隔离级别 REPEATABLE READSERIALIZABLE,第二个事务也会被阻塞,但在第一个事务提交时会抛出一个 序列化错误
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章