我要删除的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 任何人都可以面对这个问题,可以为您提供帮助吗?
答案 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,就像可以在过程中进行事务控制一样。