sql >> Databáze >  >> RDS >> Oracle

Fond připojení Tomcat jdbc – opuštěná transakce vrácení zpět

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

Tento test využívající Mysql spíše než Oracle potvrzuje tuto skutečnost:

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();
        }
    }
}

Podle http://tomcat.apache.org/tomcat-7.0 -doc/jdbc-pool.html :

Doporučuji nenastavovat removeAbandoned takže Oracle ukončí připojení po vypršení časového limitu na straně serveru, místo aby jej Tomcat uzavřel. Oracle v takovém případě pravděpodobně transakci nepotvrdí, ale budete to muset otestovat.

Případně můžete zvýšit removeAbandonedTimeout nastavení, takže váš program může dokončit a žádná připojení nebudou zrušena?

Dalším problémem, který máte, je to, že se vaše aplikace svázala s Oracle, protože se spoléháte na implementaci ovladače, kde má specifikace díru. Pokud můžete, programujte podle specifikací, abyste mohli svou aplikaci migrovat do jiné databáze, i když vím, že je to v praxi obtížné.

Zcela jiným řešením by bylo vzít open source fond připojení a rozšířit jej o AOP interceptor, který dokáže zachytit volání close a zjistěte, zda byla transakce potvrzena, a pokud ne, zavolejte rollback na připojení. To je ale docela složité řešení... :-)



  1. mysql tabulka uzamčena po pádu php

  2. úprava obrázku pomocí typu vstupního souboru

  3. Jak napsat aplikaci .Net, která funguje se SqlServerem i Oracle (nyní, když je System.Data.OracleClient zastaralý)

  4. Jak přidám další členy do svého sloupce typu ENUM v MySQL?