分块删除活动表上的多行 - 无需锁定太长时间(PostgreSQL 9.3)

Din*_*ina 10 postgresql delete plpgsql

我是 postgres 的新手,

我在实时服务器上有一个 2000 万行的表 - 我需要删除大部分行但不是全部。我想这样做而不影响访问此表的其他读/写进程(非常频繁)。

我有一种方法可以一次删除大约 100-400K 行块。在每次删除之间,我想让查询休眠 - 以便其他操作可以有机会访问此表。

我有代码,但我相信这个版本,它在查询运行的整个时间(所有睡眠)都锁定表。我怎样才能在进程休眠时真正释放表?谢谢!!

到目前为止我的代码:

CREATE SEQUENCE tmp_sq increment by 1 minvalue 1 maxvalue 53 start with 1;

DO $$

DECLARE 
w_counter integer;

BEGIN
w_counter := (SELECT nextval('tmp_sq')); 

  while w_counter < 53 loop
    raise notice 'Value: %', w_counter ;

    w_counter := (SELECT nextval('tmp_sq')); 

-- this way of breaking up the delete into chunks works for my table because of dates.
    delete from table_a where date_part('week',my_date) = w_counter;

    raise notice '     Rows Were Deleted ';

    --sleep
    raise notice 'Sleeping Now.....';
    perform pg_sleep(60);
  end loop;

END $$;
Run Code Online (Sandbox Code Playgroud)

jja*_*nes 15

表本身仅在 ROW EXCLUSIVE 模式下锁定,这不应阻止对表的任何正常操作,只能阻止诸如 DROP、ALTER 和 CREATE INDEX 之类的操作。

被删除的每一行都将在持续时间内被锁定。如果其他进程试图更新行(或自己删除它们),这应该只阻止其他进程。通常使用批量删除,您会删除其他人不关心的行,这意味着没有其他人会尝试更新它们。

如果您确实需要定期解锁所有已删除的行和表,那么您需要在单独的事务中执行删除的每个循环。在 DO 块中没有简单的方法可以做到这一点,因为整个块都在单个事务中运行。所以你应该把你的循环放在 PostgreSQL 之外,比如在 bash、perl、python 等中。