当前位置: 首页 > news >正文

Oracle-Java JDBC 连接超时之后的认知纠正

背景

  偶然读到熊老师的文章《老熊的三分地-JDBC中语句超时与事务》了解到:JAVA代码的最后正常断开数据库连接,在默认情况下,正常断开的数据库连接会自动提交没有提交的事务。
  通过文章的测试JAVA程序,可以表明,JDBC中的语句超时,只会使当前的SQL中止运行,但如果是在一个事务中,之前运行的DML语句并没有提交。这造成的后果有两种:

  1. 如果是连接池,那么超时之前更新的数据可能会被其他请求重用时得以提交,或者是在连接释放时得以提交,这造成数据的不一致,因为不是一个逻辑上有效的事务。
  2. 由于数据被更新而没有及时回滚,可能会导致应用重新发起相同的事务时被锁住。如果被锁住的会话仍然有超时中止的机制,那么这种情况就会越来越严重。
  3. 为了避免以上的两种问题,在超时后,应该主动发起一次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
[root@db ~]$ mkdir /usr/local/java
[root@db ~]$ cd /usr/local/java
[root@db java]$ mv /root/jdk-11.0.21_linux-x64_bin.tar.gz ./
[root@db java]$ tar -zxvf jdk-11.0.21_linux-x64_bin.tar.gz 
[root@db java]$ cd jdk-11.0.21
[root@db jdk-11.0.21]# pwd
/usr/local/java/jdk-11.0.21
[root@db 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
...
[root@db ~]# source /etc/profile
[root@db ~]# java -version
java version "11.0.21" 2023-10-17 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.21+9-LTS-193)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.21+9-LTS-193, mixed mode)
  • Oracle 用户环境变量
[oracle@db ~]$ cat .bash_profile 
......
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
export JAVA_HOME=/usr/local/java/jdk-11.0.21
export CLASSPATH=$JAVA_HOME/lib
export PATH=$PATH:$JAVA_HOME/bin
......
[oracle@db ~]$ source .bash_profile 
[oracle@db ~]$ java -version
java version "11.0.21" 2023-10-17 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.21+9-LTS-193)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.21+9-LTS-193, mixed mode)
  • JAVA代码:
    [oracle@db 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 name='x' where id=1");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
[oracle@db java_oracle]$ ls ojdbc8.jar TestTimeout.java
  • 通过javac 编译代码生成:TestTimeout.class
[oracle@db java_oracle]$ javac TestTimeout.java
[oracle@db java_oracle]$ ls
ojdbc8.jar TestTimeout.class  TestTimeout.java
  • 测试执行java
[oracle@db java_oracle]$ java -cp .:ojdbc8.jar TestTimeout
连接成功!
SID:387
Insert t1 succeed!
Update t2 succeed!
关闭连接!
  • 查看数据
TWO@phytest1:1489> select * from t1;ID SID                  NAME
---------- -------------------- ----------------1 387                  xx
  • 配置sqlplus 显示: 用户名@实例名:SID
[oracle@db ~]$ cat /u01/oracle/11.2.0.3/product/sqlplus/admin/glogin.sql
SET TERMOUT OFF
DEFINE sqlprompt=none
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
[oracle@db ~]$ sqlplus / as sysdba
SYS@phytest1:387> 

复现:熊老师文章的操作流程

  • SID:1489 表准备:T1、T2:
TWO@phytest1:1489> create table t1 ( id number primary key,sid varchar2(20),name varchar2(20));
Table created.
TWO@phytest1:1489> create table t2 ( id number primary key,sid varchar2(20),name varchar2(20));
Table created.
TWO@phytest1:1489> insert into t2 values (1,userenv('sid'),'a');
1 row created.
TWO@phytest1:1489> commit;
Commit complete.
TWO@phytest1:1489> select * from t2;ID SID                  NAME
---------- -------------------- --------------1 1489                 a
  • SID:1489 将T2表中ID=1的记录进行UPDATE操作,但是不提交。
TWO@phytest1:1489>  update t2 set name='y' where id=1;
1 row updated.
TWO@phytest1:1489> 
  • 执行java 程序
[oracle@db java_oracle]$ java -cp .:ojdbc8.jar TestTimeout
连接成功!
SID:659
Insert t1 succeed!
  • sid:74 执行update表T2时会被锁住
SYS@phytest1:74> set line 800
SYS@phytest1:74> col EVENT for a50
SYS@phytest1:74> select sid,event,sql_id from v$session where sid=659;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
  • 操作截图

    image.png

  • 查看事务的状态
select start_time,xidusn,xidslot,xidsqn,status from v$transaction where ses_addr=(select saddr from v$session where sid=387);select * from v$lock where sid=387;
-- 取TM锁对象id(v$lock.ID1)
select owner,object_name,object_type from dba_objects where object_id in (256012);
  • 操作截图

    image.png

  • 如熊老师文章所示,超时关闭连接后insert 插入成功

    image.png

验证下Oracle与Mysql 退出

Oracle 退出小测试,结果已提交

  

image.png

Mysql 退出小测试,结果已回滚

  

image.png

总结

  • 1、通过复现熊老师的测试,确认JDBC在会话超时后会把未提交的数据进行提交处理;
  • 2、通过验证Oracle与Mysql 的退出,Oracle 确实在关闭自动提交后,退出仍然会提交;
  • 3、程序在做异常处理时一定要加rollback;
  • 4、重要的事情说三遍:细节、细节、细节,不能忽略,不能有惯性思维;
  • 5、Python-JDBC-Oracle 测试脚本下载

欢迎赞赏支持或留言指正

image.png

相关文章:

Oracle-Java JDBC 连接超时之后的认知纠正

背景 偶然读到熊老师的文章《老熊的三分地-JDBC中语句超时与事务》了解到:JAVA代码的最后正常断开数据库连接,在默认情况下,正常断开的数据库连接会自动提交没有提交的事务。   通过文章的测试JAVA程序,可以表明,JDB…...

自定义数据集使用框架的线性回归方法对其进行拟合

代码 import torch import numpy as np import torch.nn as nncriterion nn.MSELoss()data np.array([[-0.5, 7.7],[1.8, 98.5],[0.9, 57.8],[0.4, 39.2],[-1.4, -15.7],[-1.4, -37.3],[-1.8, -49.1],[1.5, 75.6],[0.4, 34.0],[0.8, 62.3]])x_data data[:, 0] y_data data…...

15天基础内容-5

day13 【String类、StringBuilder类】 主要内容 String类常用方法【重点】 String类案例【重点】 StringBuilder类【重点】 StringBuilder类常用方法【重点: append】 StringBuilder类案例【理解】 第一章String类 1.1 String类的判断方法 String类实现判断功能…...

82,【6】BUUCTF WEB .[CISCN2019 华东南赛区]Double Secret

进入靶场 提到了secret,那就访问 既然这样,那就传参看能不能报错 这个页面证明是有用的 传参长一点就会报错,传什么内容无所谓 所以网站是flask框架写的 有一个颜色深一点,点开看看 rc4加密url编码 import base64 from urllib…...

Android WebView 中网页被劫持的原因及解决方案

文章目录 一、原因分析二、解决方案一览三、解决方案代码案例3.1 使用 HTTPS3.2 验证 URL3.3 禁用 JavaScript3.4 使用安全的 WebView 设置3.5 监控网络请求3.6 使用安全的 DNS 四、案例深入分析4.1 问题4.2 分析 五、结论 在 Android 应用开发中,WebView 是一个常用…...

特朗普政府将开展新网络攻击

近日,特朗普政府已表态:减少物理战争,网络战将代替,以实现美国的全球优势。 特朗普也指示美国网络司令部可以在没有总统批准的情况下开展更广泛行动,尤其是应对一些突发事件,这其实成为了后续美国通过网络…...

快递代取项目Uniapp+若依后端管理

快递接单代取得uniappspringboot项目 实际效果图...

arcgis短整型变为长整型的处理方式

1.用QGIS的重构字段工具进行修改,亲测比arcgis的更改字段工具有用 2.更换低版本的arcgis10.2.2,亲测10.5和10.6都有这个毛病,虽然官方文档里面说的是10.6.1及以上 Arcgis10.2.2百度链接:https://pan.baidu.com/s/1HYTwgnBJsBug…...

06、Redis相关概念:缓存击穿、雪崩、穿透、预热、降级、一致性等

Redis相关概念:缓存击穿、雪崩、穿透、预热、降级、一致性等 Redis缓存雪崩、缓存击穿、缓存预热热点key、缓存降级、短链接、分布式锁秒杀、预减库存、 堆外缓存Redis架构设计、Redis动态刷新、Redis和DB双写一致性、过期删除策略、集群数据倾斜等一、缓存雪崩 缓…...

嵌入式基础 -- PCIe 控制器中断管理之MSI与MSI-X简介

PCIe 控制器中断管理技术文档 1. 背景 在现代计算机系统中,中断是设备与 CPU 通信的重要机制,PCIe 控制器提供了从传统线中断到基于消息的中断(MSI/MSI-X)的演进,以提升中断处理效率和可扩展性。x86 和 ARM 架构虽然…...

websocket实现

由于安卓资源管理器展示的路径不尽相同,各种软件保存文件的位置也不一定一样.对于普通用户上传文件时,查找文件可能是一个麻烦的事情.后来想到了一个办法,使用pc端进行辅助上传. 文章目录 实现思路1.0 实现定义web与客户端通信数据类型和数据格式web端websocket实现web端对客户…...

unity学习20:time相关基础 Time.time 和 Time.deltaTime

目录 1 unity里的几种基本时间 1.1 time 相关测试脚本 1.2 游戏开始到现在所用的时间 Time.time 1.3 时间缩放值 Time.timeScale 1.4 固定时间间隔 Time.fixedDeltaTime 1.5 两次响应时间之间的间隔:Time.deltaTime 1.6 对应测试代码 1.7 需要关注的2个基本…...

【C++】特殊类设计、单例模式与类型转换

目录 一、设计一个类不能被拷贝 (一)C98 (二)C11 二、设计一个类只能在堆上创建对象 (一)将构造函数私有化,对外提供接口 (二)将析构函数私有化 三、设计一个类只…...

scratch七彩六边形 2024年12月scratch三级真题 中国电子学会 图形化编程 scratch三级真题和答案解析

目录 scratch七彩六边形 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、…...

代码随想录刷题day16|(哈希表篇)349.两个数组的交集

目录 一、哈希表理论基础 二、集合set在哈希法中的应用 三、相关算法题目 四、相关知识点 1.set集合特点和常用方法 1.1 set集合概述 1.2 set集合特点 1.3 常用方法 2.set集合转换成数组 法1:另新建一个数组 法2:将结果集合转为数组 ▲ 3.数组…...

Synology 群辉NAS安装(6)安装mssql

Synology 群辉NAS安装(6)安装mssql 写在前面mssql 2019:成功安装说明,这个最终成功了 mssql 2022没有成功1. pull image2.启动mssql docker container 远程连接 写在前面 mssq是一个重要节点。 这是因为我对mysql没有一丝好感。虽然接触了许…...

2025年美赛B题-结合Logistic阻滞增长模型和SIR传染病模型研究旅游可持续性-成品论文

模型设计思路与创新点: 建模的时候应该先确定我们需要建立什么类的模型?优化类还是统计类?这个题需要大量的数据分析,因此我们可以建立一个统计学模型。 统计学建模思路:观察规律,建立模型,参…...

Hook 函数

什么是hook函数? 在计算机编程中,hook函数是指在特定的事件发生时被调用的函数,用于在事件发生前或后进行一些特定的操作。通常,hook函数作为回调函数被注册到事件处理器中,当事件发生时,事件处理器会自动…...

蓝桥杯模拟算法:蛇形方阵

P5731 【深基5.习6】蛇形方阵 - 洛谷 | 计算机科学教育新生态 我们只要定义两个方向向量数组,这种问题就可以迎刃而解了 比如我们是4的话,我们从左向右开始存,1,2,3,4 到5的时候y就大于4了就是越界了&…...

DeepSeek-R1解读:纯强化学习,模型推理能力提升的新范式?

DeepSeek-R1解读:纯强化学习,模型推理能力提升的新范式? 1. Impressive Points2. 纯强化学习,LLM推理能力提升新范式?2.1 DeepSeek-R1-Zero2.2 DeepSeek-R1 3. 端侧模型能力提升:蒸馏>强化学习 1. Impre…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

C++ 基础特性深度解析

目录 引言 一、命名空间(namespace) C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用(reference)​ C 中的引用​ 与 C 语言的对比​ 四、inline(内联函数…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...