如果需要花费太多时间关闭连接池,如何强制关闭连接?

时间:2017-06-06 07:14:19

标签: java oracle jdbc database-connection ojdbc

有时关闭连接需要花费大量时间,例如超过10分钟到1小时,或者更糟,甚至是无限期,具体取决于查询的重度或速度。

在客户端取消查询的情况下,因为它花费了太多时间,我想尽快释放使用的基础连接。

我尝试取消PreparedStatement,关闭它,然后关闭结果集,然后最后关闭连接。几乎立即取消。关闭PreparedStatement和ResultSet需要花费太多时间,我必须将它包装在具有超时的Callable中,以便在适当的时候跳过该进程并继续关闭连接本身。我还没有什么运气可以尝试。

我该如何处理?我不能简单地让连接不公开,我不能让用户等待10分钟才能进行另一次类似的查询。

另外,导致连接关闭的原因是花费太多时间?还有什么我能做的吗?您认为Oracle查询提示会有帮助吗?

顺便说一句,我正在通过瘦型驱动程序使用Oracle JDBC。

更新:

显然,可以通过在connectionCacheProperties中配置TimeToLive属性来强制关闭连接,该属性会在特定时间内关闭连接。但是,我需要的是根据需要。这值得一提,因为这证明可以像连接池那样强制关闭它。事实上,我甚至在日志中收到以下消息。

ORA-01013: user requested cancel..

2 个答案:

答案 0 :(得分:1)

主要功能:

  String g_sid = "";

主题1:

  String sql = ...;
  Connection conn = ...your connection func...;

  Statement stmt = conn.createStatement();
  ResultSet rset = stmt.executeQuery( "SELECT sid from v$mystat");
  if (rset.next()) g_sid = rset.getString("sid");
  rset.close();
  // now to the actual long-running SQL
  ResultSet rset = stmt.executeQuery( sql );
  // 
  stmt.close();

主题2:

  String serialN = "";
  Connection conn = ...your admin connection func...

  Statement stmt = conn.createStatement();
  ResultSet rset = stmt.executeQuery( "SELECT serial# serialN from v$session where sid=" + g_sid );
  if (rset.next()) {
    serialN = rset.getString("serialN"); 
    stmt.execute("alter system kill session '" + g_sid + "," + serialN + "'");
  }
  stmt.close();
  // probably keep the admin connection open for further maintenance
  //

答案 1 :(得分:1)

这是我们在POW中使用的,而不是“将更改系统授予$ UID”作为SYS拥有的程序(简化工作版本):

CREATE OR REPLACE procedure SYS.kill_session(in_sid varchar2)
as
  l_serial number;
  l_runsql varchar2(1000) := 'alter system kill session ''$1,$2'' immediate';
begin
  begin
  select serial# into l_serial from v$session where username =
  (
    SELECT USER FROM DUAL
  ) and sid=in_sid and rownum<=1;
  exception when no_data_found then
    raise_application_error( -20001, 'Kill candidate not found');
  end;
  l_runsql := replace( l_runsql, '$1', in_sid);
  l_runsql := replace( l_runsql, '$2', l_serial);
  execute immediate l_runsql;
end;
/

这样你只能杀死自己的会话。