我有一个大表测试,其中 user_id 2 有 500000 条记录。所以我想以 100 条记录为一组删除这条记录,但它给出了错误。这是我的查询:
delete from test where test_id in (select test_id
from test where User_id = 2 limit 100 )
错误:元组同时更新
什么问题。我该如何解决。
我有一个大表测试,其中 user_id 2 有 500000 条记录。所以我想以 100 条记录为一组删除这条记录,但它给出了错误。这是我的查询:
delete from test where test_id in (select test_id
from test where User_id = 2 limit 100 )
错误:元组同时更新
什么问题。我该如何解决。
您的普通子选择最多可获取 100 行,但不会锁定它们以防止写访问。并发事务可以更新或删除这些行中的一个或多个,然后
DELETE
才能锁定行(至少使用默认隔离级别READ COMMITTED
)。这将导致您的错误消息。要防御这种竞争条件,请锁定
SELECT
withFOR UPDATE
(或其他选项)中的行:以一致的顺序执行此操作,以防止多个事务之间的死锁以不同的顺序收集锁并最终相互阻塞。
还有更好的解决方案。最好的选择是
FOR UPDATE SKIP LOCKED
在 Postgres 9.5 或更高版本中:考虑升级到当前版本的 Postgres。
最后我得到了解决方案,我只是在重新索引表,现在它可以正常工作了。
谢谢大家的建议。
您可能想尝试:
将获取要删除的候选行与删除它们分开
例如:
CREATE TEMP TABLE tmp_test1 AS SELECT test_id FROM test WHERE user_id = 2;
创建临时表 tmp_test2 AS SELECT * FROM tmp_test1 LIMIT 100;
{当 tmp_test2 有行时循环}
DELETE FROM test WHERE test_id IN(SELECT test_id FROM tmp_test2);
DELETE FROM tmp_test1 WHERE test_id IN(SELECT test_id FROM tmp_test2);
截断表 tmp_test2;
插入到 tmp_test2 SELECT * FROM tmp_test1 LIMIT 100;
{结束循环}
删除 0.5M 行?
用户 2 的数据占表的百分比是多少?
如果它不止一个分数,您可以考虑在没有这些数据的情况下重新创建表。