【问题标题】:ERROR: out of shared memory错误:共享内存不足
【发布时间】:2013-05-05 15:13:14
【问题描述】:

我有一个插入给定数量的测试记录的查询。 它看起来像这样:

CREATE OR REPLACE FUNCTION _miscRandomizer(vNumberOfRecords int)
RETURNS void AS $$
declare
    -- declare all the variables that will be used
begin
    select into vTotalRecords count(*) from tbluser;
    vIndexMain := vTotalRecords;

    loop
        exit when vIndexMain >= vNumberOfRecords + vTotalRecords;

        -- set some other variables that will be used for the insert
        -- insert record with these variables in tblUser
        -- insert records in some other tables
        -- run another function that calculates and saves some stats regarding inserted records

        vIndexMain := vIndexMain + 1;
        end loop;
    return;
end
$$ LANGUAGE plpgsql;

当我对 300 条记录运行此查询时,它会引发以下错误:

********** Error **********

ERROR: out of shared memory
SQL state: 53200
Hint: You might need to increase max_locks_per_transaction.
Context: SQL statement "create temp table _counts(...)"
PL/pgSQL function prcStatsUpdate(integer) line 25 at SQL statement
SQL statement "SELECT prcStatsUpdate(vUserId)"
PL/pgSQL function _miscrandomizer(integer) line 164 at PERFORM

函数 prcStatsUpdate 如下所示:

CREATE OR REPLACE FUNCTION prcStatsUpdate(vUserId int)
RETURNS void AS
$$
declare
    vRequireCount boolean;
    vRecordsExist boolean;
begin
    -- determine if this stats calculation needs to be performed
    select into vRequireCount
        case when count(*) > 0 then true else false end
    from tblSomeTable q
    where [x = y]
      and [x = y];

    -- if above is true, determine if stats were previously calculated
    select into vRecordsExist
        case when count(*) > 0 then true else false end
    from tblSomeOtherTable c
    inner join tblSomeTable q
       on q.Id = c.Id
    where [x = y]
      and [x = y]
      and [x = y]
      and vRequireCount = true;

    -- calculate counts and store them in temp table
    create temp table _counts(...);
    insert into _counts(x, y, z)
    select uqa.x, uqa.y, count(*) as aCount
    from tblSomeOtherTable uqa
    inner join tblSomeTable q
       on uqa.Id = q.Id
    where uqa.Id = vUserId
      and qId = [SomeOtherVariable]
      and [x = y]
      and vRequireCount = true
    group by uqa.x, uqa.y;

    -- if stats records exist, update them; else - insert new
    update tblSomeOtherTable 
    set aCount = c.aCount
    from _counts c
    where c.Id = tblSomeOtherTable.Id
      and c.OtherId = tblSomeOtherTable.OtherId
      and vRecordsExist = true
      and vRequireCount = true;

    insert into tblSomeOtherTable(x, y, z)
    select x, y, z
    from _counts
    where vRecordsExist = false
      and vRequireCount = true;

    drop table _counts;
end;
$$ LANGUAGE plpgsql;

看起来该错误是内存在某处堆积的结果,但由于我创建了临时表,使用它并立即删除(据我了解释放内存),我不知道这怎么可能。

更新

我更新了 prcStatsUpdate 函数来代表我拥有的实际函数。我只是将表名和列名替换为通用名称。 我第一次没有发布的原因是它主要是非常简单的sql操作,我认为它不会有任何问题。

另外,你从哪里开始计算行数?它说错误在第 25 行,但这不可能是真的,因为如果你从头开始计数,第 25 行是where 子句中的一个条件。你是从begin开始数的吗?

有什么想法吗?

【问题讨论】:

  • 我更新了我的问题。感谢您建议放置整个代码。
  • 您是否尝试增加 max_locks_per_transaction?
  • 我还没有。在我这样做之前,我想我会问是否有人可以指出我可能错过的错误。我想了解导致这种情况发生的原因。
  • 你查过 max_locks_per_transaction 控制什么吗?

标签: postgresql loops memory


【解决方案1】:

直到事务结束时删除临时表时才会释放锁。

看到related answer

如果可能,您应该重新组织代码以在函数外部创建临时表并在函数内部截断/填充它。

【讨论】:

    【解决方案2】:

    PSQLException error out of shared memory 的快速解决方法是设置

    max_locks_per_transaction

    PostgreSQL 配置文件中的参数,它指定为每个事务分配的对象锁的数量(如果有语句/例程可以在大量表上完成)

    注意:更新后需要重启postgresql

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-13
      • 2011-03-09
      • 2016-09-01
      • 2019-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多