主要代码如下:
BEGIN
  ......  OPEN G_CUR_RPT_ITEM;
  LOOP
    FETCH G_CUR_RPT_ITEM INTO G_V_RPT_ITEM;
    EXIT WHEN G_CUR_RPT_ITEM%NOTFOUND;    ......
  END LOOP;  CLOSE G_CUR_RPT_ITEM;EXCEPTION
WHEN OTHERS THEN
  ......个人分析:
上面代码是打开一个CURSOR,对其循环操作,如果说循环里的语句没有任何异常,那么会正常的关闭CURSOR不会有任何问题,可是一但循环语句有一个异常了,这种写法的程序将会跳过CLOSE,执行EXCEPTION部分,这样就会有一个CURSOR没有关闭而继续占用内存,当数据库运行很长时间后,这样开这的CURSOR过多最终会耗尽数据库的内存。
我的程序抛出了下面的错误,可能就是由于这张CURSOR没有关闭,被耗尽内存引起的,错误代码如下:
ORA-04030: out of process memory when trying to allocate 16392 bytes (hash-join subh,QERHJ list array) 请大家帮我看看我分析的对不对,这里我提两个问题
1、CURSOR长期打开,Oracle不会自动收回其内存将其关闭吗?
2、如果目前内存被耗尽,是不是重启数据库就可以恢复内存?除了重启外还有什么解决方法?下面是我改进后的程序:只是在发生错误时也将CURSOR关闭。
BEGIN
  ......  OPEN G_CUR_RPT_ITEM;
  LOOP
    FETCH G_CUR_RPT_ITEM INTO G_V_RPT_ITEM;
    EXIT WHEN G_CUR_RPT_ITEM%NOTFOUND;    ......
  END LOOP;  CLOSE G_CUR_RPT_ITEM;EXCEPTION
WHEN OTHERS THEN
  CLOSE G_CUR_RPT_ITEM;
  ......

解决方案 »

  1.   

    1、CURSOR长期打开,Oracle不会自动收回其内存将其关闭吗?是的2、如果目前内存被耗尽,是不是重启数据库就可以恢复内存?除了重启外还有什么解决方法?关闭打开这个游标的会话,也会释放内存
      

  2.   

    小第进来顶一下!
    支持楼主的问题,支持楼主在异常中也关闭游标解决此问题。
    libin_ftsafe(子陌红尘)
    能解释一下会话吗?
    怎样关闭一个会话
      

  3.   

    1. 从V$session,V$process查找会话的ID
    2. alter system kill xxx,xxx
    3, 或者用操作系统命令杀会话KILL- 9(UNIX),ORAKILL(WINDOWS)
      

  4.   

    在异常处理中,用回滚语句rollback也可关闭游标
      

  5.   

    也可以在异常中判断当前会话的游标状态,如果是打开的将其close.
      

  6.   

    请问王长林,在异常里只要有rollback就可以关闭游标吗?即使在异常里没有写close语句也可以吗?
      

  7.   

    BEGIN
      ......  OPEN G_CUR_RPT_ITEM;
      LOOP
        FETCH G_CUR_RPT_ITEM INTO G_V_RPT_ITEM;
        EXIT WHEN G_CUR_RPT_ITEM%NOTFOUND;    ......
      END LOOP;  CLOSE G_CUR_RPT_ITEM;EXCEPTION
    WHEN OTHERS THEN
      ROLLBACK WORK;在异常里写上rollback就能在发生异常时关闭上面的游标吗?还是要像下面这个写才可以?BEGIN
      ......  OPEN G_CUR_RPT_ITEM;
      LOOP
        FETCH G_CUR_RPT_ITEM INTO G_V_RPT_ITEM;
        EXIT WHEN G_CUR_RPT_ITEM%NOTFOUND;    ......
      END LOOP;  CLOSE G_CUR_RPT_ITEM;EXCEPTION
    WHEN OTHERS THEN
      CLOSE G_CUR_RPT_ITEM;
      ROLLBACK WORK;
      

  8.   

    cursor不是分两种吗?其实我觉得如果你采用隐式CURSOR那是会自己关闭的,但是我不推荐使用,因此我觉得如果再用CURSOR的时候,最好还是一定要手动关闭...