JDBC-SQL execution timeout

 

 The setQueryTimeout method is defined in the Statement interface of java jdbc. This method API:

void setQueryTimeout(int seconds)
                     throws SQLException
Sets the number of seconds the driver waits for a Statement object to execute to the given number of seconds. If this limit is exceeded, a SQLException is thrown.
The JDBC driver must apply this restriction to the execute, executeQuery, and executeUpdate methods.
JDBC driver implementations can also apply this restriction to ResultSet methods
(Refer to the driver vendor documentation for details).
parameter:
seconds - query timeout limit in seconds; 0 means no limit
throws:
SQLException - if a database access error occurs, this method is called on a closed Statement, or the condition seconds >= 0 is not met
See also:
getQueryTimeout()

 

  That is, if the database jdbc driver supports it, the timeout exception can be implemented, which is particularly useful for certain situations:

      1. The execution time of sql is very long, which causes the execution thread to block for a long time and reduces the throughput of request processing.

      2. sql execution produces a deadlock, or waits for another connection to release the lock, and keeps blocking.

       

 The way MyBatis sets setQueryTimeout:

   

  1. Configure in the xml of mybatis configuration:

   

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!--Set the SQL execution timeout time, throw an exception when the timeout expires-->
        <setting name="defaultStatementTimeout" value="30"/>
    </settings>
</configuration>

  2. Configure the timeout in the xml of the sql configuration, the priority is higher than 1

 

<update id="updateName" timeout="20">
        update my_table set name=#{param1} where  id= #{param2}
    </update>

 

 Where does MyBatis call the Statement.setQueryTimeout method? ?

  

public abstract class BaseStatementHandler implements StatementHandler {
 @Override
  public Statement prepare(Connection connection) throws SQLException {
    ErrorContext.instance().sql(boundSql.getSql());
    Statement statement = null;
    try {
      statement = instantiateStatement(connection);
      setStatementTimeout(statement);//Set sql execution timeout
      setFetchSize(statement);
      return statement;
    } catch (SQLException e) {
      closeStatement(statement);
      throw e;
    } catch (Exception e) {
      closeStatement(statement);
      throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
    }
  }
   protected void setStatementTimeout(Statement stmt) throws SQLException {
    Integer timeout = mappedStatement.getTimeout();
    Integer defaultTimeout = configuration.getDefaultStatementTimeout();
    if (timeout != null) {
	// If timeout is set in the configured SQL ?
	// Such as:
	// <update id="updateName" timeout="20">
       //    update test_user set name=#{param1} where  id= #{param2}
       //  </update>
      //
      stmt.setQueryTimeout(timeout);
    } else if (defaultTimeout != null) {
	//If the global timeout is set
	//As set under Settings in the xml configuration file of mybatis:
       // <setting name="defaultStatementTimeout" value="20"/>
      stmt.setQueryTimeout(defaultTimeout);
    }
  }
  
}

 

 

 If the jdbc driver supports it, the timeout will throw an exception.

  Tested: PostgreSQL 9.5 support.

  Example exception:

   

Caused by: org.postgresql.util.PSQLException: ERROR: canceling statement due to user request
  在位置:while updating tuple (0,12) in relation "my_table"
	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:570)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:420)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:413)
	at com.alibaba.druid.pool.DruidPooledPreparedStatement.execute(DruidPooledPreparedStatement.java:493)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:45)
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:73)
	at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49)
	at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:115)
	at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:75)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:170)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:386)

 

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326683336&siteId=291194637