如何在Postgres中删除多个Blob大对象

时间:2018-11-16 17:04:47

标签: postgresql blob postgresql-9.5

我要删除的pg_largeobject_metadata表中有一百万行。到目前为止,我尝试过的是:

  • 一个简单的选择lo_unlink(oid)很好
  • perform lo_unlink(oid)在10000行循环中也可以正常工作
  • 因此,当我递归删除多行时,出现此错误。我无法增加max_locks_per_transaction,因为它是由AWS管理的。
  

错误:共享内存不足   提示:您可能需要增加max_locks_per_transaction。   上下文:SQL语句“ SELECT lo_unlink(c_row.oid)” PL / pgSQL函数inline_code_block第21行位于   PERFORM SQL状态:53200

这是我尝试编写的程序,但仍然出现共享内存不足错误。

DO $proc$
DECLARE
v_fetch     bigInt;
v_offset    bigInt;
nbRows      bigInt;
c_row       record;
c_rows      CURSOR(p_offset bigInt, p_fetch bigInt) FOR SELECT oid FROM pg_largeobject_metadata WHERE oid BETWEEN 1910001 AND 2900000 OFFSET p_offset ROWS FETCH NEXT p_fetch ROWS ONLY;

BEGIN
v_offset    := 0;
v_fetch     := 100;
select count(*) into nbRows FROM pg_largeobject_metadata WHERE oid BETWEEN 1910001 AND 2900000;
RAISE NOTICE 'End loop nbrows = %', nbRows;
LOOP                                        -- Loop the different cursors 
    RAISE NOTICE 'offseter = %', v_offset;          
    OPEN c_rows(v_offset, v_fetch);
    LOOP                                    -- Loop through the cursor results
        FETCH c_rows INTO c_row;
        EXIT WHEN NOT FOUND;
        perform lo_unlink(c_row.oid);
    END LOOP;
    CLOSE c_rows;
    EXIT WHEN  v_offset > nbRows;
    v_offset := v_offset + v_fetch;         -- The next 10000 rows
END LOOP;
END;
$proc$;

我正在使用Pg 9.5 任何人都可以面对这个问题,可以为您提供帮助吗?

1 个答案:

答案 0 :(得分:1)

每个lo_unlink()都对其删除的对象进行锁定。这些锁仅在事务结束时释放,并且以max_locks_per_transaction * (max_connections + max_prepared_transactions)为上限(请参见Lock Management)。默认情况下,max_locks_per_transaction为64,将其提高几个数量级并不是一个好的解决方案。

典型的解决方案是将外部LOOP从DO块移至客户端代码,并在每次迭代时提交事务(因此,每个事务会删除10000个大对象并提交)。

从PostgreSQL版本11开始,可以在DO block内部进行COMMIT,就像可以在过程中进行事务控制一样。