2

In our web application we are running into this issue very often

ORA-01000 maximum open cursors exceeded

I understand this has to do with the code not closing the cursors (ResultSet, PreparedStatement, etc.) properly.

Sample:

public List<Employee> getAllEmployees() throws DatabaseException{
        Connection conn = DatabaseHelper.getConnection(); //Get a connection from the connection pool

        PreparedStatement pst = null;
        ResultSet rs = null;

        List<Employee> emps = new ArrayList<Employee>();
        try {
            pst = conn.prepareStatement("SELECT * FROM EMPLOYEE ORDER BY EMP_ID");
            rs = pst.executeQuery();
            while(rs.next()) {
                //Do something
            }
        } catch (SQLException e) {
            logger.error("ERROR getting all employees", e);
            throw new DatabaseException("Could not get all employees due to an internal error", e);
        } finally {
            try { pst.close(); } catch(Exception ignore) {} //Close the prepared statement
            try { rs.close(); } catch(Exception ignore) {} //Close the Resultset
            try { conn.close(); } catch(Exception ignore) {} ////Close the connection, thus returning it to the pool
        }

        return emps;
    }

Though I understand that I'm closing the cursors and the connection in the finally block, what I don't understand is how can I actually verify that the cursors are closed in the Oracle database?

I am currently running the following query (assuming my DB username is EMP)

select * from v$open_cursor where sid in (select sid from v$session where username='EMP' and program ='JDBC Thin Client');

This gives me a list of rows for open cursors for sessions connected through the JDBC thin client. But even after the pst.close(), rs.close() and the conn.close() are called, the query keeps returning the same rows, which seems to indicate that the cursors are still open.

I used JProfiler to check for leaks. However, it tells me if I'm closing the Connection objects or not, but does not tell me about PreparedStatement, Statement and ResultSet

I have already referred to the following post, and have followed the instructions, but none of them seem to answer my question, which is, how can I verify if a cursor is being closed in Oracle (using SQL Developer or some other tool)?

Link to a very exhaustive explanation on this topic

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Sriram Sridharan
  • 720
  • 18
  • 43
  • The way you are closing is wrong: the order is wrong, and you don't take into account exceptions from one, that prevent closing of the other resources. Instead you should switch to using try-with-resources which will always close in the right order, even when exceptions occur during the close, and rely on Oracle having tested their driver for closing correctly. You may also need to take into account things like prepared statement caching, etc. – Mark Rotteveel Jul 31 '18 at 12:50
  • Thank you Mark, I accept i could be wrong about the order. Could you please tel me what the right order is? As for taking into account exceptions, I have enclosed the close() for each resource into its own try-catch block so that exceptions in one close() doesn't affect the others. Am I missing something? – Sriram Sridharan Jul 31 '18 at 12:52
  • The correct order would be result set -> statement -> connection, but if you use try-with-resources, then the right order will be applied automatically. – Mark Rotteveel Jul 31 '18 at 12:53
  • Ok, but is anything wrong with the way exceptions are handled?? – Sriram Sridharan Jul 31 '18 at 13:29
  • I would look at open sessions rather than the code. Often I find the problem is somewhere other than expected. If you have enterprise manager available, you can quickly check sessions that have been around too long to see their last SQL executed and find that in the code. – JOTN Jul 31 '18 at 22:59

1 Answers1

0

First, and most important, v$open_cursor is not a list of cursors currently open. For that, I think you need some combination of v$sesstat and v$statname, but I'm not really sure.

What is your open_cursors parameter set to? I think the default is 50, but Oracle recommends setting that to at least 500.

eaolson
  • 14,717
  • 7
  • 43
  • 58
  • I tried figuring out. But still I have the feeling that I'm not satisfied. Probably as @Mark Rotteveel suggested, I'd have to rely on Oracle having tested their driver correctly. But, it would still be better if I can see it somewhere.. – Sriram Sridharan Aug 08 '18 at 12:45