在PostgreSQL中,使用UPDATE ... RETURNING对 JSONB数组进行原子追加时,返回的行中会包含并发更新吗?
我在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的行级锁会把它们串行化:
- A获得行锁
- A将
[]更新为[thumb1] - A返回
[thumb1] - B等待
- B将
[thumb1]更新为[thumb1, thumb2] - B返回
[thumb1, thumb2]
我的主要问题:
是否有可能请求A 的 RETURNING 结果已经包含请求B 附加的缩略图(例如 [thumb1, thumb2])?
换言之,RETURNING 是否总是反映紧随该条语句之后的行状态,还是可能包含在执行期间提交的另一事务所作的更改?
我对大约1000个并发请求进行了压力测试,第一条请求始终只返回它自己的缩略图。我想知道这是否是PostgreSQL的保证,还是仅仅由时序引起的结果。
解决方案
答案取决于所使用的 事务隔离级别:
- 如果你使用的是默认的隔离级别
READ COMMITTED,PostgreSQL的行为将完全符合你的预期:第二个事务将在第一个提交前被阻塞,并且它将看到该行处于第一个事务所放入的状态。 - 如果你使用更高的隔离级别
REPEATABLE READ或SERIALIZABLE,第二个事务也会被阻塞,但在第一个事务提交时会抛出一个 序列化错误。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。