sqloracle-database

"Maximum open cursors exceeded": How to know for some DB object how many cursors are open?


In Finacle, sometimes users are facing "The resource is busy" error due to the oracle error generated in back-end as "Maximum open cursors exceeded". Not that this error comes often, but we want to take precautionary measures and that is why we are trying to generate an alert for the Finacle engineers i.e. for ourselves so that whenever the maximum no of cursors exceeds for some DB object, we can get the alert. For that, we need to know what is the command to know how many cursors are open for the DB objects at a given time. Can somebody guide us on this matter please.

Another thing to clear my concept, does Oracle use any default cursor for querying a table? Because, my guess is this error is generating because number of users for this software has increased and there are lots of sessions getting opened for the same DB object with select and update query and that is how number of open cursors is getting increased.


Solution

  • I guess you don't close your cursors after you use it, For example, I customized the open_cursor parameter to allow user to have only one opened cursor (3 cursors oracle uses for its own needs):

    SQL> conn / as sysdba
    Connected.
    SQL> alter system set open_cursors=4 scope=memory
      2  /
    
    System altered.
    
    SQL> conn hr/hr
    Connected.
    SQL> var l_cursor refcursor;
    SQL> ed
    Wrote file afiedt.buf
    
      1  begin
      2    open :l_cursor for select 1 from dual;
      3* end;
    SQL> /
    
    PL/SQL procedure successfully completed.
    
    SQL> var l_cursor1 refcursor;
    SQL> ed
    Wrote file afiedt.buf
    
      1  begin
      2    open :l_cursor1 for select 1 from dual;
      3* end;
    SQL> /
    begin
    *
    ERROR at line 1:
    ORA-01000: maximum open cursors exceeded
    

    As you see I face the same error you had. Let's close the l_cursor cursor (the print command displays a cursor's content and closes it) and then open l_cursor1 once again:

    SQL> print l_cursor
    
             1
    ----------
             1
    
    SQL> ed
    Wrote file afiedt.buf
    
      1  begin
      2    open :l_cursor1 for select 1 from dual;
      3* end;
    SQL> /
    
    PL/SQL procedure successfully completed.
    
    SQL> print l_cursor1
    
             1
    ----------
             1
    

    As you can see Oracle can successfully open the l_cursor1 cursor.

    As a quick solution of your problem you can increase the open_cursor parameter with command (you system might need additional resources to keep the current performance):

    alter system set open_cursors=800 scope=both 
    

    I used scope=memory, because I want this demo doesn't affect my system after the database server is restarted. You have to specify scope=both to persist this parameter in spfile. But I guess you have to exam your system and find out if you have opened cursors that aren't used anymore.

    Your guess about "does Oracle use any default cursor for querying a table?" is true, Oracle uses cursors to query tables, you can make sure:

    SQL> var l_cursor refcursor;
    SQL> ed
    Wrote file afiedt.buf
    
      1  begin
      2      open :l_cursor for select 1 from dual;
      3* end;
    SQL> /
    
    PL/SQL procedure successfully completed.
    
    SQL> select * from employees;
    select * from employees
                  *
    ERROR at line 1:
    ORA-00604: error occurred at recursive SQL level 1
    ORA-01000: maximum open cursors exceeded
    
    SQL> print l_cursor
    
             1
    ----------
             1
    SQL> select * from employees;
    
    EMPLOYEE_ID FIRST_NAME           LAST_NAME
    ----------- -------------------- -------------------------
    EMAIL                     PHONE_NUMBER         HIRE_DAT JOB_ID         SALARY
    ------------------------- -------------------- -------- ---------- ----------
    COMMISSION_PCT MANAGER_ID DEPARTMENT_ID
    -------------- ---------- -------------
            205 Shelley              Higgins
    ...
    

    To get all opened cursors check this answer