Reputation: 42773
I have a query like this:
UPDATE table1 SET
col = 'some value'
WHERE id = X
RETURNING col1, (SELECT col2 FROM table2 WHERE id = table1.table2_id FOR UPDATE);
So, this query will lock both tables, table1
and table2
, right? But which one will be locked first?
Upvotes: 1
Views: 234
Reputation: 246788
The execution plan for the query will probably look like this:
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)
That suggests that the row in table1
is locked first.
Looking into the code, I see that ExecUpdate
first calls EvalPlanQual
, where the updated tuple is locked, and only after that calls ExecProcessReturning
where the RETURNING
clause is processed.
So yes, the row in table1
is locked first.
So far, I have treated row locks, but there are also the ROW EXCLUSIVE
locks on the tables themselves:
The tables are all locked in InitPlan
in execMain.c
, and it seems to me that again table1
will be locked before table2
here.
Upvotes: 1