代码之家  ›  专栏  ›  技术社区  ›  Mayo

存储过程执行异常-增加超时或修复问题

  •  3
  • Mayo  · 技术社区  · 14 年前

    在我的世界里,任何超过30秒的东西都需要在部署到生产环境之前进行性能修复,只有少数例外(遗留代码、疯狂报告等)。向我建议的选项是将超时时间从30秒(由前端开发人员明确添加)增加到180秒。

    我的问题是: 采取简单的方法和增加超时有什么风险?如果可能,请提供支持您观点的文章链接,以便我参考。

    如果你认为这不是问题,也可以随意插话。

    5 回复  |  直到 14 年前
        1
  •  2
  •   jvilalta    14 年前

    随着全球超时时间的增加,您可能会遇到以下几个问题:

    1. 拒绝服务攻击。
    2. 服务器上的资源耗尽。

    当您增加超时时,您要告诉服务器的是,它需要保持用于服务该请求的线程运行。服务器的线程数是有限的,因此它长时间运行的线程是一个不可用于服务其他请求的线程。如果有很多请求需要很长时间才能运行,那么最终会耗尽线程,服务器将失去响应。

    这对您来说是否重要取决于对该特定存储过程发出了多少请求。如果每隔一段时间只有一个请求,那也没什么大不了的。但是,全局设置超时的问题是,它现在适用于所有请求,因此,如果有其他请求可能需要很长时间才能运行,您也将延长它们的持续时间。

        2
  •  5
  •   Adam Musch    14 年前

    有两件事要做:

    获取存储过程的SQL跟踪。

    exec dbms_monitor.session_trace_enable(binds => false, waits => true);
    exec poor_performing_procedure();
    exec dbms_monitor.session_trace_disable();
    

    查看哪些语句运行的频率,以及运行它们所花费的时间。

    将钩子添加到存储过程代码中的DBMS_分析器中。

    我的所有包中都有这样的代码,因此我可以通过设置包变量来确定是否对它们进行分析:

    PROCEDURE profiler_control(p_start_stop IN VARCHAR2, p_run_comm IN VARCHAR2, p_ret OUT BOOLEAN) AS
      l_ret_code INTEGER;
    BEGIN
      l_ret_code:=dbms_profiler.internal_version_check;
      IF l_ret_code !=0 THEN
        p_ret:=FALSE;
      ELSIF p_start_stop NOT IN ('START','STOP') THEN
        p_ret:=FALSE;
      ELSIF p_start_stop = 'START' THEN
        l_ret_code:=DBMS_PROFILER.START_PROFILER(run_comment1 => p_run_comm);
        IF l_ret_code=0 THEN
          p_ret:=TRUE;
        ELSE
          p_ret:=FALSE;
        END IF;
      ELSIF p_start_stop = 'STOP' THEN
        l_ret_code:=DBMS_PROFILER.FLUSH_DATA;
        l_ret_code:=DBMS_PROFILER.STOP_PROFILER;
        IF l_ret_code=0 THEN
          p_ret:=TRUE;
        ELSE
          p_ret:=FALSE;
        END IF;
      END IF;
    END profiler_control;
    

    create or replace procedure poorly_performing_procedure() 
    begin
      if run_profiler then
        profiler_control('START', 'poorly_performing_procedure', g_retval);
      end if;
    ...
      if run_profiler then
        profiler_control('STOP', 'poorly_performing_procedure', g_retval);
      end if;
    end poorly_performing_procedure;
    /
    

    Oracle提供脚本(一个名为 profiler.sql )您可以使用获取漂亮的报告,以显示每个PL/SQL语句/操作在运行期间执行的次数。这里有一个 link 到10g的DBMS_PROFILER文档。

        3
  •  2
  •   Quassnoi    14 年前

    如果确实希望过程完成,则应将其作为后台任务运行(而不是在脚本上下文中),并在可通过访问的资源中报告其状态 AJAX 或者是普通的一页。

    如果过程在脚本上下文中运行,则每当脚本终止时 Oracle 会话也将终止,如果尚未完成,则该过程将回滚。

    这可能是由于超时以外的原因造成的(连接中断、用户关闭页面等)

        4
  •  1
  •   Ben Hoffman    14 年前

    我不认为将超时时间增加到180秒是个好主意。我在一家快速发展的公司工作了两年。在这段时间里,我们有几十个存储过程有移动执行时间。他们开始跑步时不到1秒,然后跑了30秒,最后跑了两三分钟。一旦他们达到2分钟,就会导致站点超时,我们将捕获它,并重写过程以提高效率。长话短说,如果你把时间增加到180秒,那意味着你可能会在一个月内将超时窗口增加到360秒,然后在两个月内增加到720秒。你可以看到这是怎么回事。如果其他人不同意,那么您需要了解他们是从哪里来的,因为任何类型的数据增长都会降低您的性能。

        5
  •  1
  •   Bob Jarvis - Слава Україні    14 年前

    1. 增加超时时间,然后
    2. 鼓励外部供应商解决该问题。

    正如其他人所说,出于各种原因,增加超时不是一个好的解决方案。鼓励外部供应商提供帮助(例如,威胁要用竞争对手的应用程序替换他们的应用程序,或者在问题得到解决之前拒绝支付许可证费用)可能是你最好的选择。一般来说,你想与之谈论此事的人是销售人员,而不是技术人员。一般来说,技术人员不会对收入的损失大惊小怪,因为这不会直接影响他们。销售员

    另一方面,如果您可以修改数据库,那么最好按照@Adam Munsch的建议去做,找出哪些SQL语句运行得如此缓慢。通过添加一两个索引,您可能能够显著改善这种情况。

    祝你好运