[JDBC/Oracle]設置Statement.setQueryTimeout(seconds)並不好用 原因:環境問題


對比實驗:https://www.cnblogs.com/xiandedanteng/p/11960320.html

注:setQueryTimeout語句還是好用的,但有些環境不支持,下文是在單位虛擬機上的Oracle發生的事情,而setQueryTimeout語句在我家機器上的Oracle是支持的,詳情請見。

本以為,遇到其它session導致行鎖發生的情況,設置Statement.setQueryTimeout(seconds)就好了,至少不會讓程序等待太長時間,但是事與願違,我發現無論是設置自動Commit還是手動commit,setQueryTimeout都不好用.

似乎有人也遇到了和我一樣的情況:https://community.oracle.com/thread/552257

我的數據庫是: select * from v$version;

Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
PL/SQL Release 12.2.0.1.0 - Production
"CORE 12.2.0.1.0 Production"
TNS for Linux: Version 12.2.0.1.0 - Production
NLSRTL Version 12.2.0.1.0 - Production

兩端設置超時無效的程序如下:

package tablelock;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.log4j.Logger;

public class Deleter {
    private static Logger log = Logger.getLogger(Deleter.class);
    
    public void doDelete() {
        Connection conn = null;
        Statement stmt = null;
        
        try{
            Class.forName(DBParam.Driver).newInstance();
            conn = DriverManager.getConnection(DBParam.DbUrl, DBParam.User, DBParam.Pswd);
            conn.setAutoCommit(false);
            stmt = conn.createStatement();
            stmt.setQueryTimeout(1);// It dosen't work
            
            String sql="delete from TestTB17 where id=2";
            int deleted=stmt.executeUpdate(sql);
            
            log.info("Deleter deleted "+deleted+" records.");
            
            conn.commit();
            log.info("committed.");
        } catch (Exception e) {
            e.printStackTrace();
            //System.out.print(e.getMessage());
        } finally {
            try {
                stmt.close();
                conn.close();
            } catch (SQLException e) {
                System.out.print("Can't close stmt/conn because of " + e.getMessage());
            }
        }
    }
    
    public static void main(String[] args) {
        Deleter d=new Deleter();
        d.doDelete();
    }
}

 

package tablelock;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.log4j.Logger;

public class Deleter2 {
    private static Logger log = Logger.getLogger(Deleter2.class);
    
    public void doDelete() {
        Connection conn = null;
        Statement stmt = null;
        
        try{
            Class.forName(DBParam.Driver).newInstance();
            conn = DriverManager.getConnection(DBParam.DbUrl, DBParam.User, DBParam.Pswd);
            stmt = conn.createStatement();
            stmt.setQueryTimeout(1);// It dosen't work
            
            String sql="delete from TestTB17 where id=3";
            int deleted=stmt.executeUpdate(sql);
            
            log.info("Deleter deleted "+deleted+" records.");
        } catch (Exception e) {
            e.printStackTrace();
            //System.out.print(e.getMessage());
        } finally {
            try {
                stmt.close();
                conn.close();
            } catch (SQLException e) {
                System.out.print("Can't close stmt/conn because of " + e.getMessage());
            }
        }
    }
    
    public static void main(String[] args) {
        Deleter2 d=new Deleter2();
        d.doDelete();
    }
}

 

在以下程序的log.info處設置斷點就能使上面兩個Deleter執行不下去:

package tablelock;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.log4j.Logger;

public class Selecter {
    private static Logger log = Logger.getLogger(Selecter.class);
    
    public void doSelectfor() {
        Connection conn = null;
        Statement stmt = null;
        
        try{
            Class.forName(DBParam.Driver).newInstance();
            conn = DriverManager.getConnection(DBParam.DbUrl, DBParam.User, DBParam.Pswd);
            conn.setAutoCommit(false);
            stmt = conn.createStatement();
            
            String sql="select * from TestTB17 for update";
            stmt.executeUpdate(sql);
            
            log.info("Will block other session before commit/rollback.");
            
            conn.commit();
            log.info("committed.");
        } catch (Exception e) {
            System.out.print(e.getMessage());
        } finally {
            try {
                stmt.close();
                conn.close();
            } catch (SQLException e) {
                System.out.print("Can't close stmt/conn because of " + e.getMessage());
            }
        }
    }
    
    public static void main(String[] args) {
        Selecter d=new Selecter();
        d.doSelectfor();
    }
}

 具體是何原因還有待查.

--To be continued-- 2019-11-29 10:47


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM