Is INSERT … SELECT an atomic transaction?

梦想与她 提交于 2021-02-10 18:15:40

问题


I use a query like this:

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 *;

My question is about FOR UPDATE t2 SKIP LOCKED. Should I use it here? Or will Postgres lock these rows automatically with INSERT SELECT ON CONFLICT till the end of the transaction?

My goal is to prevent other apps from (concurrently) capturing rows with the inner SELECT which are already captured by this one.


回答1:


Yes, FOR UPDATE OF t2 SKIP LOCKED is the right approach to prevent race conditions with default Read Committed transaction isolation.

The added SKIP LOCKED also prevents deadlocks. Be aware that competing transactions might each get a partial set from the SELECT - whatever it could lock first.

While any transaction is atomic in Postgres, it would not prevent another (also atomic) transaction from selecting (and inserting - or at least trying) the same row, because SELECT without FOR UPDATE does not take an exclusive lock.

The Postgres manual about transactions:

A transaction is said to be atomic: from the point of view of other transactions, it either happens completely or not at all.

Related:

  • Postgres UPDATE … LIMIT 1

Clarifications:

  • An SQL DML command like INSERT is always automatically atomic, since it cannot run outside a transaction. But you can't say that INSERT is a transaction. Wrong terminology.

  • In Postgres all locks are kept until and released at the end of the current transaction.



来源:https://stackoverflow.com/questions/46831831/is-insert-select-an-atomic-transaction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!