2010-11-09 61 views
3

我有一些我認爲可能會發生內存泄漏的PL/SQL代碼。每次運行它時,它似乎都比之前的運行速度慢,速度慢,即使現在我正在減小輸入大小。我是可疑的代碼是從一個遊標使用批量收集,像這樣PL/SQL - 檢查內存泄漏?

open c_myCursor(in_key); 
     fetch c_myCursor bulk collect into io_Array; /*io_array is a parameter, declared as in out nocopy */ 
    close c_myCursor; 

我不知道如何檢查,看看是什麼導致這種放緩填充的數組。我知道在Oracle中有一些表格跟蹤這種內存使用情況,但我不確定是否可以查看這些表格並找到回到我的代碼正在做的事情的有用信息。

此外,我試圖註銷會話,並在約10-15分鐘後重新登錄,仍然非常緩慢。

Oracle版本是10.2


因此,原來有其他數據庫活動。幾乎在我開始更改和測試代碼的同時,DBA決定運行一些大的插入和更新作業。我懷疑我的代碼是根本原因,因爲我沒有被告知其他工作正在運行(我完全凍結了所有事情,而其他所有的開發人員都感到惱火後,我只聽說過這個其他工作)。這可能是我的代碼越來越慢的原因。

有沒有一種方法可以以編程方式找到它,比如查詢插入/更新大量數據的會話,以防DBA忘記告訴我下次他這樣做?

+4

是PL/SQL甚至容易受到內存泄漏? SQL是一種非常高級的語言,通常不會有這個問題。 – 2010-11-09 20:10:45

回答

2

V $ sessmetric是一個快速的方法,看看有什麼資源,每個會話使用 - CPU,physical_reads,logical_reads,pga_memory等

+0

有趣的......有沒有辦法看到*會話使用什麼*對象?在這種情況下,問題是一個表正在被另一個進程更新。我想如果這是一張不同的桌子,我不會有這樣的問題。有沒有另外一種觀點來加入這個觀察對象的問題?或者即使我可以看到正在執行的語句可能就足夠了。 。 – FrustratedWithFormsDesigner 2010-11-12 21:42:55

+1

選擇V $ sessmetric *,SQL_TEXT,從V $ sessmetric sql_fulltext 左外連接 (SELECT * FROM V $ SQL WHERE users_executing> 0)queries_running上V $ sessmetric.session_id = queries_running.parsing_schema_id; – 2010-11-13 00:11:04

0

http://www.dba-oracle.com/t_plsql_dbms_profiler.htm描述了DBMS_PROFILER。我想你的代碼中最慢的部分可以連接到內存泄漏。無論如何,如果你回到原來的問題,它變得越來越慢,那麼首先要做的是看看什麼是緩慢的,然後假設內存泄漏。

聽起來好像你在執行之間沒有提交,重做日誌越來越大。可能這是DB需要提供讀一致性的原因。

您還可以檢查企業管理控制檯。你使用哪個版本?切勿使用XE進行開發,因爲據我所知專業版可用於開發目的。企業管理控制檯甚至會給你建議。也許它可以告訴你一些關於你的PLSQL問題的聰明之處。

+0

有問題的代碼沒有做任何提交,但它也沒有做任何插入。沒有更新,沒有刪除。調用可疑代碼*的PL/SQL腳本*具有提交。我沒有使用XE。我將不得不看看分析器。我們的IDE是PL/SQL Developer(由Allround Automation開發),我認爲它可以自動對腳本和他們調用的代碼進行分析,但我不確定它是否描述了我需要的內容。我得看看它。 – FrustratedWithFormsDesigner 2010-11-09 21:11:33

+0

...哦,是的,我懷疑這個代碼是因爲它是修改後的包中的一些新東西之一,但它是唯一能夠執行任何數據檢索的代碼,並且它是填充數組的唯一代碼。 – FrustratedWithFormsDesigner 2010-11-09 21:12:28

2

「我試着註銷會話並在大約10-15分鐘後重新登錄,仍然非常慢。」

假設您在* nix平臺上使用傳統的專用連接,這幾乎可以排除任何內存泄漏。當你建立一個新的數據庫連接時,oracle會爲它分出一個新的進程,所有的PGA內存都屬於這個進程,當會話被斷開並且進程終止時,它將被釋放(由OS)。

如果您使用的是共享服務器連接,則會話將使用屬於進程但共享內存的內存。這可能會更容易受到任何內存泄漏問題的影響。

Windows的工作方式並不完全相同,因爲它不會爲每個會話分開一個單獨的進程,而是在單個Oracle進程下有一個單獨的線程。再一次,我懷疑這會更容易發生內存泄漏。

我通常會首先查找其他問題,並可能從查詢基礎c_myCursor開始。也許它必須閱讀更多舊數據才能獲得最新數據?

+0

工作站是Windows,服務器是unix(不知道是哪一種)。我不知道他們是共享連接還是專用的。 'c_myCursor'正在查看的數據非常靜態,只有在我們從DBA請求它時才從主服務器刷新,並且一段時間沒有。 – FrustratedWithFormsDesigner 2010-11-09 22:13:37

0

如果您的查詢返回非常多數據您的集合可能會非常大,比如說10 000 000條記錄 - 這可能是可疑內存使用的一點。

您可以通過記錄您批量收集到的集合的大小來進行檢查。如果是較大的是10 000(只是一個粗略的估計,這取決於課程的數據),你可以考慮拆分,並與數據的部分工作,水木清華這樣的:

declare 
    cursor cCur is select smth from your_table; 
    -- 
    type TCur is table of cCur%rowtype index by pls_integer; 
    -- 
    fTbl TCur; 
begin 
    open cCur; 
    loop 
    fTbl.delete; 
    fetch cCur bulk collect into fTbl limit 10000; 
    exit when cCur%notfound; 

    for i in 1 .. fTbl.count loop 
     --do your wok here 
    end loop; 
    end loop; 
    close cCur; 
end; 

既然你說該表被聲明爲我知道你不能直接重寫這樣的邏輯,只是考慮方法論,也許這可以幫助你。