2013-05-10 127 views
0

我有一個插入給定數量的測試記錄的查詢。 它看起來是這樣的:錯誤:共享內存不足

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開始計數?

任何想法?

+0

我更新了我的問題。感謝您提供整個代碼的建議。 – Dmitry 2013-05-10 23:29:51

+0

您是否嘗試增加max_locks_per_transaction? – 2013-05-11 00:56:17

+0

我還沒有。在我這樣做之前,我想我會問是否有人可以指出我可能錯過的錯誤。我想了解是什麼導致了這種情況發生。 – Dmitry 2013-05-11 02:31:01

回答

2

直到事務結束時才釋放鎖定,臨時表被刪除。

看到related answer

如果可能,您應該重新組織代碼以在函數外部創建臨時表並在函數內截斷/填充它。