诸城网站价格,做网站用什么技术好,装饰工程预算与报价,怎么做网站免费背景 偶然读到熊老师的文章《老熊的三分地-JDBC中语句超时与事务》了解到#xff1a;JAVA代码的最后正常断开数据库连接#xff0c;在默认情况下#xff0c;正常断开的数据库连接会自动提交没有提交的事务。 通过文章的测试JAVA程序#xff0c;可以表明#xff0c;JDB…背景 偶然读到熊老师的文章《老熊的三分地-JDBC中语句超时与事务》了解到JAVA代码的最后正常断开数据库连接在默认情况下正常断开的数据库连接会自动提交没有提交的事务。 通过文章的测试JAVA程序可以表明JDBC中的语句超时只会使当前的SQL中止运行但如果是在一个事务中之前运行的DML语句并没有提交。这造成的后果有两种
如果是连接池那么超时之前更新的数据可能会被其他请求重用时得以提交或者是在连接释放时得以提交这造成数据的不一致因为不是一个逻辑上有效的事务。由于数据被更新而没有及时回滚可能会导致应用重新发起相同的事务时被锁住。如果被锁住的会话仍然有超时中止的机制那么这种情况就会越来越严重。为了避免以上的两种问题在超时后应该主动发起一次ROLLBACK操作。 今天正好有国产数据库工程师师给我们培训的时候也提到了这一点表示“JDBC连接ORACLE在断开连接时会把未提交的事务进行提交在Oracle 23ai版本进行了修复其它数据库都是回滚事务。” 这着zhuo实有点刷新我对Oracle的基础认知。这是一篇对自己认知纠正的测试文章。复现一下熊老师的测试实践出真知。
环境准备
Oracle 版本 SQL*Plus: Release 11.2.0.3.0 Production on Tue Nov 19 21:32:31 2024 安装JAVA [rootdb ~]$ mkdir /usr/local/java
[rootdb ~]$ cd /usr/local/java
[rootdb java]$ mv /root/jdk-11.0.21_linux-x64_bin.tar.gz ./
[rootdb java]$ tar -zxvf jdk-11.0.21_linux-x64_bin.tar.gz
[rootdb java]$ cd jdk-11.0.21
[rootdb jdk-11.0.21]# pwd
/usr/local/java/jdk-11.0.21
[rootdb jdk-11.0.21]# vi /etc/profile
...
export JAVA_HOME/usr/local/java/jdk-11.0.21
export CLASSPATH$JAVA_HOME/lib
export PATH$PATH:$JAVA_HOME/bin
...
[rootdb ~]# source /etc/profile
[rootdb ~]# java -version
java version 11.0.21 2023-10-17 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.219-LTS-193)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.219-LTS-193, mixed mode) Oracle 用户环境变量
[oracledb ~]$ cat .bash_profile
......
export NLS_LANGAMERICAN_AMERICA.AL32UTF8
export JAVA_HOME/usr/local/java/jdk-11.0.21
export CLASSPATH$JAVA_HOME/lib
export PATH$PATH:$JAVA_HOME/bin
......
[oracledb ~]$ source .bash_profile
[oracledb ~]$ java -version
java version 11.0.21 2023-10-17 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.219-LTS-193)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.219-LTS-193, mixed mode)
JAVA代码 [oracledb java_oracle]$ cat TestTimeout.java
import java.sql.*;public class TestTimeout {public static Connection getConnection() throws Exception {String driver oracle.jdbc.driver.OracleDriver;String url jdbc:oracle:thin:10.10.5.64:1521/phytest1;Class.forName(driver);return DriverManager.getConnection(url, two, two);}public static void main(String args[]) {test1();}public static void test1() {Connection conn null;Statement pstmt null;try {conn getConnection();conn.setAutoCommit(false);pstmt conn.createStatement();pstmt.setQueryTimeout(60);System.out.println(连接成功);ResultSet rs pstmt.executeQuery(select userenv(sid) sid from dual);while (rs.next()) {System.out.println(SID: rs.getString(sid));}rs.close();pstmt.execute(insert into t1 values (1,userenv(sid),xx));System.out.println(Insert t1 succeed);pstmt.execute(update t2 set namex where id1);System.out.println(Update t2 succeed);conn.commit();} catch (Exception e) {e.printStackTrace();try {System.out.println(等待......);Thread.sleep(300000);} catch (Exception f) {}} finally {try {System.out.println(关闭连接);pstmt.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}}
} 将ojdbc8_jar.zip放在项目目录,下载ojdbc8_jar.zip
[oracledb java_oracle]$ ls ojdbc8.jar TestTimeout.java 通过javac 编译代码生成TestTimeout.class
[oracledb java_oracle]$ javac TestTimeout.java
[oracledb java_oracle]$ ls
ojdbc8.jar TestTimeout.class TestTimeout.java测试执行java
[oracledb java_oracle]$ java -cp .:ojdbc8.jar TestTimeout
连接成功
SID:387
Insert t1 succeed
Update t2 succeed
关闭连接查看数据
TWOphytest1:1489 select * from t1;ID SID NAME
---------- -------------------- ----------------1 387 xx
配置sqlplus 显示 用户名实例名:SID
[oracledb ~]$ cat /u01/oracle/11.2.0.3/product/sqlplus/admin/glogin.sql
SET TERMOUT OFF
DEFINE sqlpromptnone
COLUMN sqlprompt NEW_VALUE sqlprompt
SELECT USER |||| NVL(_CONNECT_IDENTIFIER, global_name )||:|| userenv(sid) sqlprompt FROM global_name;
SET SQLPROMPT sqlprompt
UNDEFINE sqlprompt
SET TERMOUT ON
col NAME format a50
col VALUE format a50
set lin 250
set pagesize 500
[oracledb ~]$ sqlplus / as sysdba
SYSphytest1:387
复现熊老师文章的操作流程
SID:1489 表准备T1、T2
TWOphytest1:1489 create table t1 ( id number primary key,sid varchar2(20),name varchar2(20));
Table created.
TWOphytest1:1489 create table t2 ( id number primary key,sid varchar2(20),name varchar2(20));
Table created.
TWOphytest1:1489 insert into t2 values (1,userenv(sid),a);
1 row created.
TWOphytest1:1489 commit;
Commit complete.
TWOphytest1:1489 select * from t2;ID SID NAME
---------- -------------------- --------------1 1489 a
SID:1489 将T2表中ID1的记录进行UPDATE操作但是不提交。
TWOphytest1:1489 update t2 set namey where id1;
1 row updated.
TWOphytest1:1489
执行java 程序
[oracledb java_oracle]$ java -cp .:ojdbc8.jar TestTimeout
连接成功
SID:659
Insert t1 succeed
sid:74 执行update表T2时会被锁住
SYSphytest1:74 set line 800
SYSphytest1:74 col EVENT for a50
SYSphytest1:74 select sid,event,sql_id from v$session where sid659;SID EVENT SQL_ID
---------- ------------------------------------- ----------659 enq: TX - row lock contention 3b3b7s22dv13t
查看锁信息 col blocker for a10
SELECT (SELECT usernameFROM v$sessionWHERE SID a.SID) blocker, a.SID, is blocking,(SELECT usernameFROM v$sessionWHERE SID b.SID) blockee, b.SIDFROM v$lock a, v$lock bWHERE a.BLOCK 1 AND b.request 0 AND a.id1 b.id1 AND a.id2 b.id2;BLOCKER SID ISBLOCKING BLOCKEE SID
---------- ---------- ----------- ------------------------------ ----------
TWO 659 is blocking TWO 277
操作截图 查看事务的状态
select start_time,xidusn,xidslot,xidsqn,status from v$transaction where ses_addr(select saddr from v$session where sid387);select * from v$lock where sid387;
-- 取TM锁对象id(v$lock.ID1)
select owner,object_name,object_type from dba_objects where object_id in (256012); 操作截图 如熊老师文章所示超时关闭连接后insert 插入成功
验证下Oracle与Mysql 退出
Oracle 退出小测试结果已提交 Mysql 退出小测试结果已回滚 总结
1、通过复现熊老师的测试确认JDBC在会话超时后会把未提交的数据进行提交处理2、通过验证Oracle与Mysql 的退出Oracle 确实在关闭自动提交后退出仍然会提交3、程序在做异常处理时一定要加rollback;4、重要的事情说三遍细节、细节、细节不能忽略不能有惯性思维5、Python-JDBC-Oracle 测试脚本下载 欢迎赞赏支持或留言指正