postgresql - 如何在 Postgres 中删除多个 blob 大对象
问题描述
我要删除的 pg_largeobject_metadata 表中有数百万行。到目前为止我尝试过的是:
- 一个简单的选择
lo_unlink(oid)
工作正常 - 10000 行的循环中的A
perform lo_unlink(oid)
也可以正常工作 - 因此,当我递归删除多行时,我会收到此错误。我无法增加
max_locks_per_transaction
,因为它是由 AWS 管理的。
错误:共享内存不足提示:您可能需要增加 max_locks_per_transaction。上下文:SQL 语句“SELECT lo_unlink(c_row.oid)”PL/pgSQL 函数 inline_code_block 第 21 行,执行 SQL 状态:53200
这是我尝试编写的程序,但仍然出现Out of shared memory ERROR。
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 有没有人遇到过这个问题,可以帮忙吗?
解决方案
每个都lo_unlink()
在它删除的对象上获取一个锁。这些锁仅在事务结束时被释放,并且被限制max_locks_per_transaction * (max_connections + max_prepared_transactions)
(参见锁管理)。默认情况下max_locks_per_transaction
是 64,将其提高几个数量级并不是一个好的解决方案。
典型的解决方案是将 DO 块中的外部 LOOP 移动到客户端代码中,并在每次迭代时提交事务(因此每个事务会删除 10000 个大对象并提交)。
从 PostgreSQL 版本 11 开始,DO 块内的 COMMIT是可能的,就像过程中的事务控制是可能的一样。
推荐阅读
- cassandra - 系统规格与 Cassandra 配置参数的关系
- node.js - 如何使用 mongoose 在 mongodb 中存储用户定义的(动态)日期和时间?
- web - 在 Odoo 网站生成器上无法使用 SSL/TLS
- c - “未找到多重引导标头”,内核最少
- android - 使用默认 Google 推荐时的版本冲突
- vuejs2 - Vee 验证 if/else 输入字段
- javascript - 正则表达式替换为 IE11/Edge 上的搜索参数引发 ReferenceError
- javascript - 我如何替换数据中的数据(JSRender)
- php - 查找除单词“www”之外的所有 alpha newric 的模式
- xml - 如何使用 Julia 处理 zip 文件