PostgreSQL:我是否需要锁定 table 以避免在使用子查询查找 JSONB 数组中的更新索引的更新期间出现并发错误?

PostgreSQL: Do I need to lock table to avoid concurrency errors during update that use a subquery to find the index o update in a JSONB array?

假设我想更新 customers table 中的 JSONB 列 contacts(对象数组),并且我想更新基于数组的对象的值由于子查询,在其索引上,我是否需要在执行期间锁定 table 以防止更新以避免并发问题?

换句话说,是否可以在我的两次查询执行之间更改table,因此我通过子查询选择的索引将过时?

with contact_email as (
    select ('{' || index - 1 || ', value}')::text[] as path from customers
    cross join jsonb_array_elements(contacts) with ordinality arr(contact, index)
    where contact->>type = 'email' and name = 'john'
)
update customers
set contacts = jsonb_set(contacts,contact_email.path,'"john@example.com"', false)
from contact_email
where and name = 'john'

-- `customers` table has a `name` column and a `contacts` column (jsonb)
-- `contacts` column contains things like `[{"type":"email","value":"x@y.z", …}]`

在上面的示例中,如果 contacts 列中的数组在 table 读取(子查询)和更新(主查询)之间发生更改,则选择的索引将变得错误:然后我会更新错误的数组条目。

如果有什么不清楚,我可以编辑我的问题并添加更多详细信息。

查询的两部分将看到相同的数据库快照,因此数据始终一致。

如果某些并发事务在读取时间和写入时间之间更改行,结果取决于您的隔离级别:

  • 如果您是 运行 默认 READ COMMITTED 隔离,则更新将覆盖该更改或不执行任何操作(后者如果 name 已更改)

  • 如果您 运行 REPEATABLE READ 或更高,您将得到 序列化错误 并且必须重复语句