Postgresql
SELECT FOR UPDATE 如何處理 PostgreSQL 中的視圖?
為了從 PostgreSQL 中檢索域模型數據,我有時會選擇視圖而不是表。我這樣做是為了在一個查詢中返回盡可能多的資訊,而不是觸發多個查詢來解決所有關係依賴項。這主要是因為表之間存在一對一的關係,或者它們是查找表,我只需要某些列等。為了防止某些競爭條件,我使用的一種策略是
SELECT ... FOR SHARE/UPDATE
查詢。我想知道當我們開始對視圖使用它們時它們的行為如何。假設我們有兩個表
A
和B
,每個表都有一列ID
。現在,假設我們有一個視圖AB
,它是這兩個表之間的連接操作。假設這是一個笛卡爾連接:SELECT "A"."ID" AS "AID", "B"."ID" AS "BID" FROM "A" CROSS JOIN "B"
如果我們在以下情況下
SELECT FOR UPDATE
針對AB
哪些表的哪些行會被鎖定?
SELECT * FROM "AB" WHERE "AB"."AID" = :ID
SELECT * FROM "AB" WHERE "AB"."BID" = :ID
SELECT * FROM "AB" WHERE "AB"."AID" = :ID1 AND "AB"."BID" = :ID2
簡短的回答
在三種情況下,以下行將被鎖定以進行更新:
- 表“A”中具有“ID”=:ID 的行和表“B”中的所有行
- 表“B”中具有“ID”=:ID 的行和表“A”中的所有行
- 表“A”中具有“ID”= :ID1 的行和表“B”中具有“ID”= :ID2 的行
閱讀文件中的此聲明後,結果與預期的一樣:
如果鎖定子句應用於視圖或子查詢,它會影響視圖或子查詢中使用的所有表。
如何測試類似的案例
安裝擴展pgrowlocks。.
create extension if not exists pgrowlocks;
執行兩個 psql 實例。在第一個中啟動事務並執行查詢。
psql #1:
begin; select * from "AB" where "AID" = 3 and "BID" = 103 for update;
您可以在 psql 的另一個實例中看到鎖定的行。
psql #2:
select * from pgrowlocks('"B"'); locked_row | locker | multi | xids | modes | pids ------------+--------+-------+---------+----------------+-------- (0,4) | 88577 | f | {88577} | {"For Update"} | {8068} (1 row)
不要忘記在最後關閉事務(在下一次測試之前)。
psql #1:
rollback;
上述結果的第一列是
ctid
。您可以使用查詢選擇原始行:select * from "B" where ctid = '(0,4)';