Bug 54337 - StatementCache leaks statements/cursors
Summary: StatementCache leaks statements/cursors
Status: RESOLVED DUPLICATE of bug 54732
Alias: None
Product: Tomcat Modules
Classification: Unclassified
Component: jdbc-pool (show other bugs)
Version: unspecified
Hardware: PC All
: P2 normal (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-12-21 11:31 UTC by Patric Rufflar
Modified: 2013-03-22 17:34 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Patric Rufflar 2012-12-21 11:31:49 UTC
It seems that the StatementCache has issues in highly multi-threaded situations where high numbers of PreparedStatements are created.

The application quickly fails with the well-known "Internal Exception: java.sql.SQLException: ORA-01000: maximum open cursors exceeded"

Without the StatementCache the application just runs fine.
All threads invoke the same SQLs. Of course, each thread uses its own Connection exclusively.

Two things are conspicuous:

1. 
The AtomicInteger field org.apache.tomcat.jdbc.pool.interceptor.StatementCache.cacheSize 
which seems to be not in sync with the real size of the cache Map.

It's too high (higher than 50) and the StatementCache (erroneously) assumes that the cache capacity is exceeded.

I suggest calling size() on the cache Map instead.

2. 
When the capacity seems (or really is) exceeded, statement.close() will not causing to close the wrapped statement causing the cursor to leak.

The reason can be seen in org.apache.tomcat.jdbc.pool.interceptor.StatementCache$CachedStatement.closeInvoked() line: 244-288:

            closed = true;
            delegate = null;
            if (shouldClose) {
                super.closeInvoked();
            }

The delegate is set to null but only _afterwards_ super.closeInvoked() is invoked which is unable to close the underlying preparedStatement => the statement remains unclosed. It should be the other way round.

Best regards,
Patric
Comment 1 Konstantin Kolinko 2013-03-22 17:34:11 UTC
(In reply to comment #0)
> 1. 
> The AtomicInteger field
> org.apache.tomcat.jdbc.pool.interceptor.StatementCache.cacheSize 
> which seems to be not in sync with the real size of the cache Map.
> (..)

You are wrong:
Map is per-connection. Size is per-pool.

> 2. 
> When the capacity seems (or really is) exceeded, statement.close() will not
> causing to close the wrapped statement causing the cursor to leak.

Yes, it is a bug. Duplicate of 54732.

*** This bug has been marked as a duplicate of bug 54732 ***