Son*_*que 5 sql postgresql concurrency locking upsert
我使用这样的查询:
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 *;
Run Code Online (Sandbox Code Playgroud)
我的问题是关于FOR UPDATE t2 SKIP LOCKED. 我应该在这里使用它吗?或者 Postgres 会自动锁定这些行直到INSERT SELECT ON CONFLICT事务结束吗?
我的目标是防止其他应用程序(同时)捕获SELECT已被该应用程序捕获的内部行。
是的,这是通过默认的已提交读事务隔离FOR UPDATE OF t2 SKIP LOCKED来防止竞争条件的正确方法。
添加的内容SKIP LOCKED还可以防止死锁。请注意,竞争事务可能每个都会从 - 无论它首先锁定的内容中获取部分集SELECT。
虽然 Postgres 中的任何事务都是原子的,但它不会阻止另一个(也是原子的)事务选择(并插入 - 或至少尝试)同一行,因为SELECT without FOR UPDATE不采用独占锁。
Postgres关于事务的手册:
\n\n\n\n\n事务被认为是原子的:从其他事务的角度来看,它要么完全发生,要么根本不发生。
\n
有关的:
\n\n\n\n澄清:
\n\n像这样的 SQL DML 命令INSERT始终自动是原子的,因为它不能在事务之外运行。但你不能说这INSERT 是一笔交易。术语错误。
在 Postgres 中,所有锁都会保留到当前事务结束并在当前事务结束时释放。