對比實驗: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
