sql >> データベース >  >> RDS >> Oracle

Tomcatjdbc接続プール-放棄されたトランザクションのロールバック

    http://docsによると.oracle.com / javase / 7 / docs / api / java / sql / Connection.html#close()

    OracleではなくMysqlを使用したこのテストでは、この事実が確認されています。

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

    http://tomcat.apache.org/tomcat-7.0によると、 -doc / jdbc-pool.html

    removeAbandonedを設定しないことをお勧めします Oracleは、Tomcatが接続を閉じるのではなく、サーバー側でタイムアウトした後に接続を閉じるようにします。その場合、Oracleはおそらくトランザクションをコミットしませんが、これをテストする必要があります。

    または、removeAbandonedTimeoutを増やすこともできます プログラムを終了し、接続が放棄されないように設定しますか?

    もう1つの問題は、仕様に穴が開いているドライバーの実装に依存しているため、アプリケーションがOracleに関連付けられていることです。可能であれば、仕様に照らしてプログラミングし、アプリケーションを別のデータベースに自由に移行できるようにします。ただし、実際には難しいことはわかっています。

    まったく異なる解決策は、オープンソースの接続プールを取得し、closeへの呼び出しをインターセプトできるAOPインターセプターで拡張することです。 トランザクションがコミットされているかどうかを確認し、コミットされていない場合は、rollbackを呼び出します。 接続上。しかし、それは非常に複雑な解決策です... :-)



    1. MYSQL挿入送信ボタンPHP

    2. 2つの日付の間の週

    3. SQL Server Ro14でデッドロックの理由を見つける方法は?

    4. Pythonで巨大なMySQLテーブルを読み取る最速の方法