在更新时锁定一个table,在子查询中锁定另一个,先锁定哪个?
Lock one table at update and another in subquery, which one will be locked first?
我有这样的查询:
UPDATE table1 SET
col = 'some value'
WHERE id = X
RETURNING col1, (SELECT col2 FROM table2 WHERE id = table1.table2_id FOR UPDATE);
那么,这个查询将锁定两个表,table1
和 table2
,对吗?但是先锁定哪个呢?
查询的执行计划可能如下所示:
QUERY PLAN
-------------------------------------------------------------------------------------------
Update on laurenz.table1
Output: table1.col1, (SubPlan 1)
-> Index Scan using table1_pkey on laurenz.table1
Output: table1.id, table1.table2_id, 'some value'::text, table1.col1, table1.ctid
Index Cond: (table1.id = 42)
SubPlan 1
-> LockRows
Output: table2.col2, table2.ctid
-> Index Scan using table2_pkey on laurenz.table2
Output: table2.col2, table2.ctid
Index Cond: (table2.id = table1.table2_id)
这表明 table1
中的行首先被锁定。
查看代码,我看到 ExecUpdate
首先调用 EvalPlanQual
,其中更新的元组被锁定,然后才调用 ExecProcessReturning
,其中 RETURNING
子句已处理。
所以是的,table1
中的行首先被锁定。
到目前为止,我已经处理了行锁,但表本身也有 ROW EXCLUSIVE
锁:
execMain.c
中InitPlan
的表都被锁定了,我觉得table1
又会在table2
这里被锁定
我有这样的查询:
UPDATE table1 SET
col = 'some value'
WHERE id = X
RETURNING col1, (SELECT col2 FROM table2 WHERE id = table1.table2_id FOR UPDATE);
那么,这个查询将锁定两个表,table1
和 table2
,对吗?但是先锁定哪个呢?
查询的执行计划可能如下所示:
QUERY PLAN
-------------------------------------------------------------------------------------------
Update on laurenz.table1
Output: table1.col1, (SubPlan 1)
-> Index Scan using table1_pkey on laurenz.table1
Output: table1.id, table1.table2_id, 'some value'::text, table1.col1, table1.ctid
Index Cond: (table1.id = 42)
SubPlan 1
-> LockRows
Output: table2.col2, table2.ctid
-> Index Scan using table2_pkey on laurenz.table2
Output: table2.col2, table2.ctid
Index Cond: (table2.id = table1.table2_id)
这表明 table1
中的行首先被锁定。
查看代码,我看到 ExecUpdate
首先调用 EvalPlanQual
,其中更新的元组被锁定,然后才调用 ExecProcessReturning
,其中 RETURNING
子句已处理。
所以是的,table1
中的行首先被锁定。
到目前为止,我已经处理了行锁,但表本身也有 ROW EXCLUSIVE
锁:
execMain.c
中InitPlan
的表都被锁定了,我觉得table1
又会在table2
这里被锁定