Vasily, the exception depends on where the timeout occurs.

If the timeout is triggered by the driver, because you hit the
setQueryTimeout limit
http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#setQueryTimeout(int)
then yes, as per javadoc, it is up to the JDBC driver to throw an exception.


Filip




On Wed, Jul 23, 2014 at 10:04 AM, Vasily Kukhta <v.b.kuk...@gmail.com>
wrote:

> Thank you, I have changed timeBetweenEvictionRunsMillis value and it is
> working properly now. Another problem has appeared: although the timeout is
> handled correctly, no exception is thrown. I thought an SQLException would
> be thrown if query takes too long. Maybe pool does not throw exceptions at
> all in that situation?
>
> Than you!
>
>
> 2014-07-21 20:40 GMT+04:00 Daniel Mikusa <dmik...@gopivotal.com>:
>
> > On Mon, Jul 21, 2014 at 11:05 AM, Vasily Kukhta <v.b.kuk...@gmail.com>
> > wrote:
> >
> > > Hello, dear tomcat users!
> > >
> > > I am developing high-load application using tomcat jdbc connection pool
> > and
> > > Oracle database. It is very important to ensure my app to have very
> small
> > > DB query timeouts (no longer than 3 seconds) to prevent long-running
> > > queries or database slowness from blocking all my application. To
> > simulate
> > > long-running queries I have put the DB in QUIESCE state using ALTER
> > SYSTEM
> > > QUIESCE RESTRICTED statement.
> > >
> > > But it looks like the timeout values have no impact - when i begin to
> > test
> > > my application, it hangs...
> > >
> >
> > Have you taken thread dumps of your application when it "hangs"?  What do
> > these show your threads are doing?
> >
> >
> > >
> > > Here is my jdbc pool configuration:
> > >
> > >     String connprops =
> > > "oracle.net.CONNECT_TIMEOUT=3000;oracle.jdbc.ReadTimeout=3000;"
> > >                         + "oracle.net.READ_TIMEOUT=3000";
> > >
> > >
> > >                 pp.setConnectionProperties(connprops);
> > >
> > >                 pp.setDriverClassName("oracle.jdbc.OracleDriver");
> > >
> > >                 pp.setTestOnBorrow(true);
> > >                 pp.setTestOnConnect(true);
> >
> >                 pp.setTestOnReturn(true);
> > >                 pp.setTestWhileIdle(true);
> > >
> >
> > It's probably not necessary to have all of these enabled.  I usually only
> > see testOnBorrow and testWhileIdle enabled.  TestOnReturn is almost
> > worthless, in my opinion.  TestOnConnect might be helpful to catch
> > connection issues at boot, but generally a connection that is just
> created
> > should be good unless you have configuration problems.
> >
> >
> > >                 pp.setMaxWait(2000);
> > >                 pp.setMinEvictableIdleTimeMillis(20000);
> > >
> >
> >
> > >                 pp.setTimeBetweenEvictionRunsMillis(20000);
> > >
> >
> > This might be high given your aggressive settings for
> > removeAbandonedTimeout.  The timeBetweenEvictionRunsMillis setting
> dictates
> > how often the pool looks for idle connections, abandoned connections, and
> > how often it validates idle connections.  If you set this to 20 secs,
> using
> > an abandoned timeout less than 20 seconds is probably not going to be
> > accurate.
> >
> > For example, if the cleaner thread runs and your application has been
> > holding a connection for 2999ms, it won't consider the connection
> > abandoned.  However the cleaner thread won't run again for another 20
> secs
> > (based on the config value you used), thus the application can continue
> > using that connection for way over the abandoned timeout you've
> configured.
> >
> >
> > >                 pp.setValidationInterval(3000);
> > >                 pp.setValidationQuery("SELECT 1 FROM DUAL");
> > >
> >
> > Seems OK.
> >
> >
> > >
> > >                 pp.setMaxAge(3000);
> > >
> >
> > This seems pretty short and might limit how much pooling actually occurs.
> >  Also, since this is enforced when you return the connection to the pool
> > it's not going to help with your current issue.  What are you trying to
> > accomplish by setting this value so low?
> >
> >
> > >                 pp.setRemoveAbandoned(true);
> > >                 pp.setRemoveAbandonedTimeout(3);
> > >
> >
> > This is a pretty low value for abandoned timeout.  If you're hoping to
> use
> > this to limit how long a query can executed, it's probably not the best
> > approach. This will limit the amount of time that a connection can be
> > checked out of the connection pool, and unless you also configure
> > the ResetAbandonedTimer interceptor, it's going to limit the total time
> > your application has to use the connection.  If you configure the
> > ResetAbandonedTimer interceptor, it will function closer to the use case
> > you've described but it's probably not the most efficient way to
> accomplish
> > this task.
> >
> > Generally you'd set the remove abandoned timeout to reclaim connections
> > that were not properly closed, not to reclaim connections where a query
> is
> > stuck or running for a long time.  I think the jdbc driver can more
> easily
> > handle killing stuck / long running queries.  See next comment.
> >
> >
> > >
> > >
> > >
> >
> pp.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor(queryTimeout=3)");
> > >
> >
> > I'm a little surprised this isn't working for you.  By setting the
> > statement's query timeout, you're telling the jdbc driver to limit how
> long
> > each query can run.  If a query runs longer than 3 seconds, you should
> get
> > an SQLTimeoutException.  Otherwise there's an issue / limitation with
> your
> > jdbc driver.
> >
> > I would suggest setting up a test without the connection pool to validate
> > that the jdbc driver and your method for slowing down the database is
> > working correctly.  In theory this test should be something like make a
> > connection, set the query timeout, run a query and wait for the
> exception.
> >  If that does not timeout, then it's definitely not going to timeout with
> > the connection pool because the jdbc driver handles the actual timing out
> > of the request.
> >
> > If your test works, then you might want to look and see if anything else
> is
> > setting the timeout on the statement object.  The interceptor should set
> > the value when a new statement object is created.  If something else sets
> > the timeout, it would override the value set by the interceptor.
> >
> > An alternative and less aggressive approach to all of this might be to
> use
> > the SlowQueryReport or SlowQueryReportJmx interceptors.  These will watch
> > for slow queries (queries that take longer than the threshold you define
> to
> > execute) and report them.  It does not actively close or clean up long
> > running connections, but it does provide you with a lot of helpful
> > information about the problem when a query does take a while to run.
> >
> > Dan
> >
> >
> >
> > >                 dataSource = new DataSource();
> > >                 dataSource.setPoolProperties(pp);
> > >
> > >
> > > That's how i work with connections (pretty simple):
> > >
> > >     Connection conn = dataSource.getConnection();
> > >             Statement stmt = null;
> > >             ResultSet rs = null;
> > >
> > >             try {
> > >                 stmt = conn.createStatement();
> > >
> > >                 rs = stmt.executeQuery(/*some select query*/);
> > >
> > >
> > >                 if (rs.next()) {
> > >
> > >                     result = rs.getInt(1);
> > >
> > >                     /*process the result*/
> > >
> > >                 }
> > >
> > >                 rs.close();
> > >                 stmt.close();
> > >                 conn.close();
> > >
> > >             }
> > >             catch(Exception e) {
> > >                 logger.error("Exception: " + e.getMessage(), e);
> > >             }finally {
> > >                 if (conn != null) {
> > >
> > >                         if(rs!=null)
> > >                         rs.close();
> > >                     if(stmt!=null)
> > >                     stmt.close();
> > >                         conn.close();
> > >
> > >                 }
> > >             }
> > >
> > > Any ideas?
> > >
> > > Thanks in advance!
> > >
> >
>

Reply via email to