【问题标题】:Is INSERT ... SELECT an atomic transaction?INSERT ... SELECT 是原子事务吗?
【发布时间】:2017-10-19 14:06:00
【问题描述】:

我使用这样的查询:

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 的行,这些行已被此应用程序捕获。

【问题讨论】:

  • 没有理由自动锁定来自INSERT ... ON CONFLICT 中子查询的行,因为子查询执行一次。您应该明确锁定行。

标签: sql postgresql concurrency locking upsert


【解决方案1】:

是的,FOR UPDATE OF t2 SKIP LOCKED 是使用默认 Read Committed transaction isolation 防止竞争条件的正确方法。

添加的SKIP LOCKED 还可以防止死锁。请注意,相互竞争的事务可能会从 SELECT 获得部分集合——无论它可以先锁定什么。

虽然任何事务在 Postgres 中都是原子的,但它不会阻止另一个(也是原子的)事务选择(并插入 - 或至少尝试)同一行,因为 SELECT 没有 @987654329 @ 不接受exclusive lock

Postgres manual about transactions:

一个事务被称为原子:从其他事务的角度来看,它要么完全发生,要么根本不发生。

相关:


说明:

  • INSERT 这样的SQL DML 命令总是自动原子,因为它不能在事务之外运行。但是你不能说INSERT 一个事务。术语错误。

  • 在 Postgres 中,所有锁一直保留到当前事务结束时释放。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-21
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    相关资源
    最近更新 更多