Postgres 错误:元组同时更新

Sad*_*han 5 postgresql postgresql-9.0

我有一个大表测试,其中 user_id 2 有 500000 条记录。所以我想以 100 条记录为单位删除这条记录,但出现错误。这是我的查询:

delete from test where test_id in (select test_id
from test where User_id = 2 limit 100 )
Run Code Online (Sandbox Code Playgroud)

错误:元组同时更新

这是什么问题。我怎样才能解决它。

Erw*_*ter 5

您的普通子选择最多可获取 100 行,但不会锁定它们以防止写入访问。并发事务可以先更新或删除这些行中的一个或多个,然后DELETE才能锁定行(至少在默认隔离级别下READ COMMITTED)。这将导致您的错误消息。

为了防止这种竞争条件,请锁定SELECTwith FOR UPDATE(或其他选项)中的行:

DELETE FROM test t
USING (
   SELECT test_id
   FROM   test
   WHERE  User_id = 2
   ORDER  BY test_id  -- acquire locks in consistent order!
   LIMIT  100
   FOR UPDATE         -- lock rows
   ) x
WHERE x.test_id = t.test_id;
Run Code Online (Sandbox Code Playgroud)

以一致的顺序执行此操作,以防止以不同顺序收集锁并最终相互阻塞的多个事务之间发生死锁。

还有更好的解决方案。最好的选择是FOR UPDATE SKIP LOCKED在 Postgres 9.5 或更高版本中使用:

考虑升级到当前版本的 Postgres。


Sad*_*han 4

最后我得到了解决方案,我只是在重新索引表,并且它现在工作正常。

reindex table test
Run Code Online (Sandbox Code Playgroud)

谢谢大家的建议。