我有这样的查询:
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
锁:
这些表都被锁定在InitPlan
的execMain.c
中,在我看来,table1
将再次锁定在table2
之前。