3

で tomcat-jdbc 接続プールを構成しますremoveAbandoned=true。接続が放棄された場合、オプションは機能しますが、接続は単純に閉じられます。Oracle では、これは現在のトランザクションがコミットされていることを意味します (この質問を参照してください)。未完了のトランザクションはコミットされるべきではないため、これは良くありません。

接続が放棄された場合に現在のトランザクションが最初にロールバックされ、その後接続が閉じられるようにプールを構成する方法は?

試してみrollbackOnReturn=trueましたが、プールは放棄された接続にそれを使用していないようです。

編集:使用しますdefaultAutoCommit=false

編集:これが起こった1つのケースは、統合テストのデバッグでした。そのようなコミットのためにトランザクションテーブルが切り捨てられました

4

3 に答える 3

0

この変更を行うためにJDBCInterceptorを登録するだけで、閉じる前にロールバックできます。Abandon は release を呼び出し、disconnect を呼び出すため、Interceptor はこれについて通知されます。たとえば、次のようにできます。

package test;
import java.sql.SQLException;
import oracle.jdbc.OracleConnection;

import org.apache.tomcat.jdbc.pool.ConnectionPool;
import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
import org.apache.tomcat.jdbc.pool.PooledConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class RollbackInterceptor extends JdbcInterceptor {

  /**
   * Logger.
   */
private static final Logger LOG = LoggerFactory.getLogger(RollbackInterceptor.class);

/**
* {@inheritDoc}
*/
@Override
public void reset(ConnectionPool parent, PooledConnection con) {
  return;
}

/**
 * {@inheritDoc}
 */
@Override
public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) {
  // if its oracle make sure we rollback here before disconnect just in case a running TX is open
  try {
    if (con.getConnection().isWrapperFor(OracleConnection.class)) {
      if (!con.getConnection().getAutoCommit()) {
        LOG.error("Connection {} with Auto-Commit false is going to be closed. Doing an explicit Rollback here!", con);
        try {
          con.getConnection().rollback();
        } catch (SQLException e) {
          LOG.error("Failed to rollback connection {} before closing it.", con, e);
        }
      }
    }
  } catch (SQLException e) {
    LOG.error("Failed to check auto commit of connection {}", con, e);
  }
  super.disconnected(parent, con, finalizing);
}

}
于 2015-05-12T11:17:33.637 に答える
0

わかりました....放棄された接続を除外できない場合、3つのオプションしかないと思います:

  1. 放棄された接続を閉じる Tomcats ConnectionPool から Method を変更して、Rollback+Close を実行します。
  2. 接続の Close-Method を変更して、Rollback+Close を実行します
  3. タイムアウト後に DB ロールバック + 接続を閉じる (Tomcats ハンドラーを無効にする)

オプション 1 では、Tomcat ソースコードのメソッドを編集するか、HotSwapまたはJavassistを介して置き換えるか、すべて無効にして、すべての接続をループし、放棄されたものを検出して閉じる独自のメソッドを記述できます。

オプション 2 では、Connection-Interface 用に独自の Wrapper を記述して、close() 呼び出しを rollback+close に置き換え、TomCat を構成して Connection を Wrapper-Class にラップするか、HotSwap または Javassist を使用て置き換えることができます。実行時の接続クラスの Close-Method。

オプション 3 では、放棄された接続の処理全体を無効にし、特定のタイムアウト後にアイドル状態の接続を強制終了するように DB を構成します。ただし、これには、接続プール内の接続が長期間使用されていない場合に定期的に強制終了するという欠点もあります...

于 2014-09-26T08:34:24.113 に答える