PostgreSQL DROP TABLE in a loop fails with ERROR: out of shared memory
PostgreSQL DROP TABLE in a loop fails with ERROR: out of shared memory
我有一个数据库,其中有很多(3000 多个)结构相同的模式。我试图从每个模式中删除两个 table。所以我写了一个函数,它将遍历模式并尝试删除那些 tables。
当我执行我的函数时,我得到错误:共享内存不足并且没有 tables 被丢弃。
是否有可能强制 PostgreSQL 批量提交 drop table 语句?
这是我的函数(简化为有问题的问题):
CREATE OR REPLACE FUNCTION utils.drop_webstat_from_schema(schema_name character varying default '')
RETURNS SETOF record AS
$BODY$
declare
s record;
sql text;
BEGIN
for s in
select distinct t.table_schema from information_schema.tables t
where
schema_name <> '' and t.table_schema = schema_name
or
schema_name = '' and t.table_schema like 'myprefix_%'
loop
sql := 'DROP TABLE IF EXISTS ' || s.table_schema || '.webstat_hit, ' || s.table_schema || '.webstat_visit';
execute sql;
raise info '%; -- OK', sql;
return next s;
end loop;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
如您所见,该函数遍历模式集,并为每个模式构建并执行以下 SQL。
DROP TABLE IF EXISTS <schema_name>.webstat_hit, <schema_name>.webstat_visit
我猜 PostgreSQL 试图在删除之前锁定所有这些 tables,它达到了最大配置限制。
可能如果我将 max_locks_per_transaction 增加到某个固定数字,我可能会设法锁定所有 table 并删除它们。
但是 我正在寻找一种解决方案,该解决方案将逐步删除 table 并仅锁定步骤 中的那些 table。就像每 10 个模式一样,批量锁定和删除。
我可以在 Postgre 中做到这一点吗SQL 如果可以,怎么做?谢谢。
我会使用 drops 将模式循环从函数中移除。
所以让我们假设 fn_loop
plpgsql 循环模式并调用 fn_drop
。如果在 dblink 上执行 fn_drop
,则可以在 plpgsql 中批量提交。
另一种在模式之间提交的方法,在 bash 中循环,例如:
for i in $(psql -c "select nspname form pg_namespaces where blah blah"); do
psql -c "drop damn table";
done;
使用 dblink 的不同事务中的本地调用示例(注意同一数据库上 now() 的差异):
t=# do
$$
declare
_t text;
begin
for _r in 1..2 loop
select t into _t from dblink('dbname=t'::text,'select now()::text'::text) rtn (t text);
raise info '%',concat('local: ',now(),', dblink: ',_t);
end loop;
end;
$$
;
INFO: local: 2017-04-28 07:38:11.352026+00, dblink: 2017-04-28 07:38:11.355149+00
INFO: local: 2017-04-28 07:38:11.352026+00, dblink: 2017-04-28 07:38:11.358211+00
DO
Time: 6.811 ms
我有一个数据库,其中有很多(3000 多个)结构相同的模式。我试图从每个模式中删除两个 table。所以我写了一个函数,它将遍历模式并尝试删除那些 tables。
当我执行我的函数时,我得到错误:共享内存不足并且没有 tables 被丢弃。
是否有可能强制 PostgreSQL 批量提交 drop table 语句?
这是我的函数(简化为有问题的问题):
CREATE OR REPLACE FUNCTION utils.drop_webstat_from_schema(schema_name character varying default '')
RETURNS SETOF record AS
$BODY$
declare
s record;
sql text;
BEGIN
for s in
select distinct t.table_schema from information_schema.tables t
where
schema_name <> '' and t.table_schema = schema_name
or
schema_name = '' and t.table_schema like 'myprefix_%'
loop
sql := 'DROP TABLE IF EXISTS ' || s.table_schema || '.webstat_hit, ' || s.table_schema || '.webstat_visit';
execute sql;
raise info '%; -- OK', sql;
return next s;
end loop;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
如您所见,该函数遍历模式集,并为每个模式构建并执行以下 SQL。
DROP TABLE IF EXISTS <schema_name>.webstat_hit, <schema_name>.webstat_visit
我猜 PostgreSQL 试图在删除之前锁定所有这些 tables,它达到了最大配置限制。 可能如果我将 max_locks_per_transaction 增加到某个固定数字,我可能会设法锁定所有 table 并删除它们。
但是 我正在寻找一种解决方案,该解决方案将逐步删除 table 并仅锁定步骤 中的那些 table。就像每 10 个模式一样,批量锁定和删除。
我可以在 Postgre 中做到这一点吗SQL 如果可以,怎么做?谢谢。
我会使用 drops 将模式循环从函数中移除。
所以让我们假设 fn_loop
plpgsql 循环模式并调用 fn_drop
。如果在 dblink 上执行 fn_drop
,则可以在 plpgsql 中批量提交。
另一种在模式之间提交的方法,在 bash 中循环,例如:
for i in $(psql -c "select nspname form pg_namespaces where blah blah"); do
psql -c "drop damn table";
done;
使用 dblink 的不同事务中的本地调用示例(注意同一数据库上 now() 的差异):
t=# do
$$
declare
_t text;
begin
for _r in 1..2 loop
select t into _t from dblink('dbname=t'::text,'select now()::text'::text) rtn (t text);
raise info '%',concat('local: ',now(),', dblink: ',_t);
end loop;
end;
$$
;
INFO: local: 2017-04-28 07:38:11.352026+00, dblink: 2017-04-28 07:38:11.355149+00
INFO: local: 2017-04-28 07:38:11.352026+00, dblink: 2017-04-28 07:38:11.358211+00
DO
Time: 6.811 ms