One of test cases I have written recently has failed with OOM.   It 
actually tests some SELECT logic loading "heavy" records with large binary 
objects (geometries).  Investigation that I have done showed exactly the 
described below case:  prepared statements (every SELECT in my test 
produces a bit different SQL query) are cached (Apache DBCP2  library is 
used for connection pooling with an option *ds.setPoolPreparedStatements(true); 
*) and they hold last result set -  (field "lastResult" of  Query class 
that is extended by Select class).

The chain is:
JdbcPreparedStatement  ->  CommandInterface (CommandContainer) -> Prepared 
(Select -> Query) -> LocalResult (Query#lastResult).

So, prepared statements caching is ON in connection pool,  
OPTIMIZE_REUSE_RESULTS  option has default value, lot of unique SQL queries 
that leads to continuous caching of prepared statements with complete 
result set hold in memory until connection is closed or prepared statements 
are released from connection's cache.  We do not know how PS caching is 
configured in general way.
My conclusion is that  cleaning of this internally  cached result set is a 
must after we know that  logic around PS is complete and goes to the 
cache.     I understand why result set is cached within Query object. We 
need clearly distinguish cases when last result is still needed and when 
it's not needed anymore for sure.

I suppose  PreparedStatement.clearParameters() is  exactly the moment when 
we can safely get rid of the "last result".    This method is also called 
by DBCP2  before PS goes to the cache.  

Prepared class gets  empty method that can be overrided by subclasses:

    public void clearCachedResults(){
        
    }



Query class  overrides it:

    @Override
    public void clearCachedResults() {
        closeLastResult();
        lastResult = null;
    }



CommandInterface  gets a method as well:

    public void clearCachedResults();



CommandContainer  implements it as:

    public void clearCachedResults(){
        prepared.clearCachedResults();
    }



and JdbcPreparedStatement  has additional logic to call

 command.clearCachedResults();



inside of its #clearParameters().


Last result is cleaned when it's not needed, changes are minimal,  test 
case now runs successfully, additional debugging prooves cleaning of 
results and GC.


If an approach is accepted I can make change request in GIT. May be naming 
of methods could be better, let's think.

Vitali.




-- 
You received this message because you are subscribed to the Google Groups "H2 
Database" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to h2-database+unsubscr...@googlegroups.com.
To post to this group, send email to h2-database@googlegroups.com.
Visit this group at https://groups.google.com/group/h2-database.
For more options, visit https://groups.google.com/d/optout.

Reply via email to