【问题标题】:PL/SQL - check for memory leaks?PL/SQL - 检查内存泄漏?
【发布时间】:2010-11-12 09:01:12
【问题描述】:

我有一些我认为可能存在内存泄漏的 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 在下次执行此操作时忘记告诉我?

【问题讨论】:

  • PL/SQL 是否容易受到内存泄漏的影响? SQL 是一种非常高级的语言,通常不会有这个问题。

标签: oracle memory-leaks plsql


【解决方案1】:

v$sessmetric 是查看每个会话正在使用哪些资源的快速方法 - cpu、physical_reads、logical_reads、pga_memory 等。

【讨论】:

  • 有趣...有没有办法查看会话正在使用的 what 对象?在这种情况下,问题是另一个进程正在更新一个表。我想如果它是一张不同的桌子,我就不会遇到这样的问题。是否有另一种观点可以加入这个观点来查看有问题的对象?或者即使我可以看到正在执行的语句可能就足够了。
  • select v$sessmetric.*, sql_text, sql_fulltext from v$sessmetric left outer join (select * from v$sql where users_executing > 0) queries_running on v$sessmetric.session_id = queries_running.parsing_schema_id;
【解决方案2】:

“我尝试注销会话并在大约 10-15 分钟后重新登录,仍然非常慢。”

假设您在 *nix 平台上使用传统的专用连接,这几乎可以排除任何内存泄漏。当您与数据库建立新连接时,oracle 将为它分叉一个新进程,并且所有 PGA 内存都将属于该进程,并且当会话断开连接并且进程终止时它将被释放(由操作系统)。

如果您使用共享服务器连接,则会话使用属于进程和共享内存的内存。这可能更容易受到任何内存泄漏问题的影响。

Windows 的工作方式并不完全相同,因为它不会为每个会话派生一个单独的进程,而是在单个 Oracle 进程下有一个单独的线程。同样,我怀疑这更容易受到内存泄漏的影响。

我通常会首先寻找其他问题,并且可能从查询底层 c_myCursor 开始。也许它必须阅读更多旧数据才能获得新数据?

【讨论】:

  • 工作站是 Windows,服务器是 unix(不确定哪种风格)。我不知道它们是共享连接还是专用连接。 c_myCursor 正在查看的数据是相当静态的,只有在我们向 DBA 请求时才会从主服务器刷新,并且已经有一段时间没有刷新了。
【解决方案3】:

http://www.dba-oracle.com/t_plsql_dbms_profiler.htm 描述 DBMS_PROFILER。我想您的代码中最慢的部分可能与内存泄漏有关。不管怎样,如果你回到最初的问题,它变得越来越慢,那么首先要做的就是看看什么是慢的,然后假设内存泄漏。

听起来你在执行之间没有提交,并且重做日志越来越大。可能这就是 DB 需要提供读取一致性的原因。

您还可以查看企业管理控制台。您使用哪个版本?永远不要使用 XE 进行开发,因为据我所知专业版可以用于开发目的。企业管理控制台甚至可以为您提供建议。也许它可以告诉你一些关于你的 PLSQL 问题的聪明之处。

【讨论】:

  • 有问题的代码没有进行任何提交,但也没有进行任何插入。没有更新,没有删除。调用可疑代码的 PL/SQL 脚本确实有提交。我没有使用 XE。我得看看探查器。我们的 IDE 是 PL/SQL Developer(由 Allround Automation 提供),我认为它可以自动对脚本和它们调用的代码进行分析,但我不确定它是否可以分析我需要的内容。我得调查一下。
  • ...哦,是的,我怀疑这个代码,因为它是更改包中的一些新东西之一,但它是唯一可以进行任何数据检索的代码,并且它是唯一填充数组。
【解决方案4】:

如果您的查询返回 非常多 数据,您的集合可能会变得非常庞大,例如 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;

既然你说表被声明为 out nocopy 我知道你不能像这样直接重写逻辑,而只是考虑方法,也许这可以帮助你。

【讨论】:

    猜你喜欢
    • 2011-05-21
    • 1970-01-01
    • 2016-12-10
    • 2012-01-02
    • 2010-10-09
    • 2012-07-16
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多