在更新时锁定一个表,在子查询中锁定另一个表,哪一个将首先被锁定?

时间:2017-12-22 12:44:43

标签: postgresql postgresql-9.6

我有这样的查询:

UPDATE table1 SET 
col = 'some value' 
WHERE id = X
RETURNING col1, (SELECT col2 FROM table2 WHERE id = table1.table2_id FOR UPDATE);

因此,此查询将锁定两个表,table1table2,对吧?但是哪一个会被锁定?

1 个答案:

答案 0 :(得分:1)

查询的执行计划可能如下所示:

                                        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的{​​{1}}中,在我看来execMain.c将再次锁定table1