この問題について調査するために数日が経過した後、何が起こっているのか明らかに意味がないため、この質問を送信することにしました。
ケース
私のコンピュータは、ローカルの Oracle Express データベースで構成されています。@Before メソッドで OJDBC 接続 (10 接続の静的 Hikari 接続プールを使用) を開き、ロールする親クラスを拡張するいくつかの JUnit テストを含む Java プロジェクトがあります (「ベスト プラクティス」ではないことはわかっています)。 @After に戻します。
public class BaseLocalRollbackableConnectorTest {
private static Logger logger = LoggerFactory.getLogger(BaseLocalRollbackableConnectorTest.class);
protected Connection connection;
@Before
public void setup() throws SQLException{
logger.debug("Getting connection and setting autocommit to FALSE");
connection = StaticConnectionPool.getPooledConnection();
}
@After
public void teardown() throws SQLException{
logger.debug("Rollback connection");
connection.rollback();
logger.debug("Close connection");
connection.close();
}
静的接続プール
public class StaticConnectionPool {
private static HikariDataSource ds;
private static final Logger log = LoggerFactory.getLogger(StaticConnectionPool.class);
public static Connection getPooledConnection() throws SQLException {
if (ds == null) {
log.debug("Initializing ConnectionPool");
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(10);
config.setDataSourceClassName("oracle.jdbc.pool.OracleDataSource");
config.addDataSourceProperty("url", "jdbc:oracle:thin:@localhost:1521:XE");
config.addDataSourceProperty("user", "MyUser");
config.addDataSourceProperty("password", "MyPsw");
config.setAutoCommit(false);
ds = new HikariDataSource(config);
}
return ds.getConnection();
}
}
このプロジェクトには、この接続 (ローカルホスト上) を使用して Sql2o を使用してクエリ (挿入/更新および選択) を実行する何百ものテスト (並列ではない) がありますが、トランザクションと接続のクローズは外部でのみ管理されます (上記のテストによって)。ACID テストを実行するために、データベースは完全に空です。
したがって、期待される結果は、DB に何かを挿入し、アサーションを作成してからロールバックすることです。このようにして、2 番目のテストは、分離レベルを維持するために前のテストで追加されたデータを検出しません。
問題 すべてのテストを一緒に (順番に) 実行すると、90% の確率で正しく動作します。10% の 1 つまたは 2 つのテストは、ランダムに失敗します。これは、以前のテストでデータベースにダーティ データがあるためです (たとえば、一意の重複)。ログを見ると、以前のテストのロールバックは適切に行われていました。実際、データベースを確認すると、空です) このテストを、パフォーマンスが高いが同じ JDK、同じ Oracle DB XE のサーバーで実行すると、この失敗率は 50% に増加します。
テスト間で接続が異なり、毎回ロールバックが呼び出されるため、これは非常に奇妙でわかりません。JDBC Isolation レベルは READ COMMITTED であるため、同じ接続を使用したとしても、同じ接続を使用しても問題は発生しません。だから私の質問は:なぜそれが起こるのですか?何か考えはありますか?私が知っているように、JDBC ロールバックは同期的ですか?それとも完全に完了していなくても、前に進むことができる場合がありますか?
これらは私の主な DB パラメータです: プロセス 100 セッション 172 トランザクション 189