2017-10-19 54 views
1

我使用這樣的查詢:是否INSERT ...選擇原子事務?

INSERT INTO table 
    SELECT * FROM table2 t2 
     JOIN ... 
     ... 
     WHERE table2.date < now() - '1 day'::INTERVAL 
    FOR UPDATE OF t2 SKIP LOCKED 
ON CONFLICT (...) 
    DO UPDATE SET ... 
RETURNING *; 

我的問題是關於FOR UPDATE t2 SKIP LOCKED。我應該在這裏使用它嗎?或者,Postgres會自動使用INSERT SELECT ON CONFLICT鎖定這些行直到交易結束?

我的目標是阻止其他應用程序(同時)捕獲已由此人捕獲的內部SELECT的行。

+1

沒有理由在'INSERT ... ON CONFLICT'中自動鎖定子查詢中的行,因爲該子庫會執行一次。你應該明確地鎖定行。 – klin

回答

1

是的,FOR UPDATE OF t2 SKIP LOCKED是預防競爭條件的正確方法,默認爲Read Committed transaction isolation

增加的SKIP LOCKED也可以防止死鎖。請注意,競爭交易可能會從SELECT獲得部分集合 - 無論它可能首先鎖定。

在任何交易中的Postgres是原子,它不會阻止其他(也原子)交易從選擇(和插入 - 或至少嘗試)在同一行,因爲SELECT沒有FOR UPDATE不採取exclusive lock

Postgres manual about transactions

事務被認爲是原子:從視其它交易的角度來看,它要麼完全或者根本不發生。

相關:


澄清:

  • 的SQL DML像INSERT命令總是自動原子,因爲它不能在事務之外運行。但是你不能說INSERT一筆交易。錯誤的術語。

  • 在Postgres 全部鎖一直保留到當前交易結束時釋放。