So, it means that if the timeout is detected not using setQueryTimeout
method, but by the tomcat pool settings (setMaxAge or
setTimeBetweenEvictionRunsMillis), it means that no exception can be thrown
at all?

Vasily



2014-07-23 12:14 GMT+04:00 Filip Hanik <fi...@hanik.com>:

> 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