Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Pula połączeń Tomcat jdbc - wycofanie porzuconej transakcji

Według http://docs .oracle.com/javase/7/docs/api/java/sql/Connection.html#close() :

Ten test, wykorzystujący Mysql zamiast Oracle, potwierdza ten fakt:

import static org.junit.Assert.assertEquals;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.junit.Test;


public class DBTest {

    public Connection openConnection() throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        Connection c = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password");
        c.setAutoCommit(false);
        return c;
    }

    @Test
    public void testSO25886466() throws SQLException, ClassNotFoundException {

        {
            Connection c = openConnection();
            PreparedStatement delete = c.prepareStatement("delete from temp");
            delete.executeUpdate();
            c.commit();
            c.close();
        }

        {
            Connection c = openConnection();
            PreparedStatement insert = c.prepareStatement("insert into temp values ('a', 'b')");
            insert.execute();
            //c.commit(); as the op says, DONT commit!!
            c.close(); //WITHOUT having closed the statement or committing the transaction!!
        }

        {
            Connection c = openConnection();
            PreparedStatement select = c.prepareStatement("select count(*) from temp");
            select.execute();
            ResultSet rs = select.getResultSet();
            while(rs.next()){
                assertEquals(0/*i'd expect zero here!*/, rs.getInt(1));
            }
            rs.close();
            select.close();
            c.close();
        }
    }
}

Według http://tomcat.apache.org/tomcat-7.0 -doc/jdbc-pool.html :

Polecam nie ustawiać removeAbandoned aby Oracle zamykał połączenie po przekroczeniu limitu czasu po stronie serwera, a nie zamykał je Tomcat. Oracle prawdopodobnie nie zatwierdzi transakcji w takim przypadku, ale musisz to przetestować.

Alternatywnie, czy możesz zwiększyć removeAbandonedTimeout ustawienie, aby Twój program mógł się zakończyć i żadne połączenia nie zostały porzucone?

Innym problemem, który masz, jest to, że Twoja aplikacja została powiązana z Oracle, ponieważ polegasz na implementacji sterownika, w której specyfikacja ma dziurę. Jeśli możesz, programuj zgodnie ze specyfikacją, dzięki czemu możesz swobodnie migrować swoją aplikację do innej bazy danych, chociaż wiem, że w praktyce jest to trudne.

Zupełnie innym rozwiązaniem byłoby wzięcie puli połączeń typu open source i rozszerzenie jej o przechwytywacz AOP, który może przechwytywać wywołania close i sprawdź, czy transakcja została zatwierdzona, a jeśli nie, wywołaj rollback na połączeniu. To dość skomplikowane rozwiązanie... :-)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Czy Oracle 12 ma problemy z lokalnymi typami kolekcji w SQL?

  2. Oracle PL/SQL:Przekazywanie całego wiersza do procedury z wyzwalacza

  3. Jak napisać java.sql.Array do java.sql.SQLOutput w SQLData.writeSQL() dla Oracle

  4. Porównywanie dat za pomocą Dynamic Action w DatePicker Oracle Apex

  5. Wybierz max(data) nie działa, jeśli wiersze mają różne wartości, chcę tylko pobrać wiersz z najwyższą datą