Spring事务隔离级别与数据库隔离级别不一致时,该以谁为准?

Spring事务隔离级别与数据库隔离级别不一致时,该以谁为准?项目中,以Spring事务为准,因为他重写了数据库的隔离级别,但没有直接修改数据库的隔离级别

大家好,又见面了,我是你们的朋友全栈君。

原创博文,欢迎转载,转载时请务必附上博文链接,感谢您的尊重。

前言

通过本篇,你将了解到【Spring事务】与【数据库事务】的关系,以及优先级问题,我将为你一一论证。

阅读本篇,你可能会需要的博文:


正文

数据库是可以控制事务的传播和隔离级别的,Spring在之上又进一步进行了封装,可以在不同的项目、不同的操作中再次对事务的传播行为和隔离级别进行策略控制。

所以说,spring事务本质上使用数据库事务,而数据库事务本质上使用数据库锁,所以spring事务本质上使用数据库锁,开启spring事务意味着使用数据库锁。

上面的“总结”来自网络,结合自身理解与实践,的确可以最为一句精华,本文内容主要围绕这句话展开,以2个问题的形式阐明观点。

  1. Spring定义的隔离级别和数据库设置的隔离级别,二者是什么关系?
  2. 如果Spring定义的隔离级别和数据库设置的隔离级别不一样,以谁的为准?

一、两者的关系

详情在我的其他博文都有具体介绍(需要的朋友见本文【前言】提示),这里就不赘述了,我们直接对比结果。

1. 数据库的隔离级别:

MySQL 默认为 :EPEATABLE_READ;Oracle,sql server 默认为:READ_COMMITTED;READ_UNCOMMITTED 由于隔离级别较低,通常不会被使用。

√: 可能出现    ×: 不会出现
隔离级别 隔离级别的值 脏读 不可重复读 幻读
Read uncommitted(未提交读) 0
Read committed(已提交读) 1 ×
Repeatable read(可重复读) 2 × ×
Serializable(可串行化) 3 × × ×

2. Spring事务的隔离级别:

Spring事务由 @Transactional 注解实现,隔离级别由它的参数 isolation 控制,Isolation 的 Eum 类中定义了“五个”表示隔离级别的值,如下。

√: 可能出现    ×: 不会出现
Isolation的值与隔离级别 隔离级别的值 脏读 不可重复读 幻读
Isolation.DEFAULT 0
Isolation.READ_UNCOMMITTED 1
Isolation.READ_COMMITTED 2 ×
Isolation.REPEATABLE_READ 4 × ×
Isolation.SERIALIZABLE 8 × × ×

Isolation.DEFAULT 是 PlatfromTransactionManager 默认的隔离级别,它的含义是:使用数据库默认的事务隔离级别

除此之外,另外四个与 JDBC 的隔离级别是相对应的,就好像 Java 里的重写一样,所以说:Spring事务隔离级别是在数据库隔离级别之上又进一步进行了封装。

二、 不一致会怎样

既然是封装,那么Spring项目应该就是以Spring事务为准的,除非使用 @Transactional(isolation = Isolation.DEFAULT)时,才会使用数据库设置的隔离级别。

为了验证这个猜想,我们还是找到源码解读一下,从JDBC开始说起吧。

1. JDBC 加载流程

每一个 Spring 事务管理,都涉及到了与数据库的交互,也必然涉及到了JDBC连接。

JDBC 加载的流程还记得吧,肯定都被问过,有四步:注册驱动,建立连接,发起请求,输出结果。写一段伪代码:

    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    try{
        // 1.注册 JDBC 驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 2.创建链接
        System.out.println("连接数据库...");
        conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/my_db","root","root");
        // 3.发起请求
        stmt = conn.createStatement();
        String sql = "SELECT id, name, url FROM websites";
        rs = stmt.executeQuery(sql);
        // 4.输出结果
        System.out.print("查询结果:" + rs);
        // 关闭资源(演示代码,不要纠结没有写在finally中)
        rs.close();
        stmt.close();
        conn.close();
    } catch (SQLException se)
        se.printStackTrace();
    }catch(Exception e){
        e.printStackTrace();
    }

在创建连接阶段,JDBC 从数据库获取一个连接 Connection 对象,该对象不仅有连接数据库的方法,还有设置当前连接的事物隔离级别的方法。

2. Connection  源码解释

Connection 实体类中包含了 void setTransactionIsolation(int level) throws SQLException;设置设置当前连接的事物隔离级别的方法。

Spring 约定了使用 @Transactional 注解的形式实现事务特性,而隔离级别的开启,也是注解的形式实现,如:开启事务的串行级别 —— @Transactional(isolation = Isolation.SERIALIZABLE)。

Spring事务隔离级别与数据库隔离级别不一致时,该以谁为准?

源码截不全,我复制一下:

/**
* 这是 Connection 连接的部分源码
*/
public interface Connection  extends Wrapper, AutoCloseable {

    ... 

    /**
    * 尝试将此连接对象的事务隔离级别更改为给定的级别
    * 接口连接中定义的常量是可能的事务隔离级别
    */
    void setTransactionIsolation(int level) throws SQLException;

    ...
}

该方法的注释说明:尝试将此连接对象的事务隔离级别更改为给定的级别,如果在事务期间调用此方法,则结果由实现定义。

没错,强调的就是本次连接 Connection,所以,如果spring与数据库事务隔离级别不一致时,以spring为准。

3. 验证

阐述一下方法:

  • 首先,验证测试数据库的隔离级别 Select @@tx_isolation;
  • 写一个包含update,save的与测试数据库交互的方法;
  • 分别验证加上@Transactional(isolation = Isolation.SERIALIZABLE)注解前后,测试数据库的隔离级别是否变化!!

以我的测试数据库为例,结果没有发生变化,都是 READ_COMMITTED。

Spring事务隔离级别与数据库隔离级别不一致时,该以谁为准?

这只是简单的验证下Spring事务隔离级别的修改,是否会直接影响数据库的隔离级别,结论是没有。

不太严谨,但是证明了我的猜想,后期我会在Sping项目中,通过测试代码进一步验证“修改隔离级别以成功运用到Spring事务中”。

三、总结

  • 数据库是可以控制事务的传播和隔离级别的,Spring在之上又进一步进行了封装,可以在不同的项目、不同的操作中再次对事务的传播行为和隔离级别进行策略控制;
  • 项目中,以 Spring 事务为准,因为他重写了数据库的隔离级别,但没有直接修改数据库的隔离级别;
  • 项目中,如果 Spring 事务隔离级别设置为(isolation = Isolation.DEFAULT)默认数据库优先时,以数据库的隔离级别为准。

小编怀着忐忑的心情,上传了本篇博文,如果有错误,还请大佬指正!!后期也会补全自己的验证手段!!

That’s all,thank you!


我是IT无知君,您的点赞、评论和关注,是我创作的动力源泉。
学无止境,气有浩然,让我们一起加油,天涯未远,江湖有缘再见!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/141451.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • arcgis附图制作_怎么制作图片的浮雕效果

    arcgis附图制作_怎么制作图片的浮雕效果ArcGIS制作地图时可以制作出很多很炫的效果,比如地图阴影、地图晕渲效果、浮雕效果、三维效果等等。本实验讲解在ArcGIS中制作浮雕效果地图,效果如下所示:1.加载矢量数据加载实验数据包data44.rar中的秦安县乡镇矢量数据:2.缓冲区分析点击【地理处理】下拉菜单,点击【缓冲区】。输入要素选择秦安县乡镇数据,选择输出要素路径,线性单位输入-0.4,单位为千米,侧类型选择两侧,融合类型选择ALL,点击确定。缓冲区效果:3.欧氏距离分析欧氏距离工具用于计算每个像元到最近.

    2025年9月15日
    4
  • idea vim 配置[通俗易懂]

    idea vim 配置[通俗易懂]imapjkimapkjsettimeoutlen=300setkeep-english-in-normal-and-restore-in-insertsetkeep-english-in-normalsetclipboard=unnamedsetignorecase

    2022年9月30日
    3
  • excel截取指定字符之后的字符串_怎样把单元格的字符串拼接起来

    excel截取指定字符之后的字符串_怎样把单元格的字符串拼接起来函数:mid需求:提取A1单元格字符串的一部分(第四个字符算起,截取2个字符)放在A2单元格。使用:=mid(A1,4,2)

    2025年6月8日
    2
  • vscode 中 整理代码的快捷键_vscode格式化代码_vscode格式化代码快捷键

    vscode 中 整理代码的快捷键_vscode格式化代码_vscode格式化代码快捷键3 安装 VsCode 格式化代码插件搜索并安装 Beautify 格式化代码插件使用指南 打开要格式化的文件 gt F1VSCode 如何格式化或美化 js css 代码 本经验介绍在 VSCode 查看代码时 如何美化不换行的代码 以及如何格式化 vscode 格式化代码的快捷键如下 来源于这里 OnWindowsShi Alt FOnMacShift Option FOn

    2025年9月24日
    2
  • 数仓分层ods_跨境电商国内中转仓

    数仓分层ods_跨境电商国内中转仓一、ods层介绍1、保持数据原貌不做任何修改,起到备份数据的作用。2、数据采用LZO压缩,减少磁盘存储空间。100G数据可以压缩到10G以内。3、创建分区表,防止后续的全表扫描,在企业开发中大量使用分区表。4、创建外部表,在企业开发中,除了自己用的临时表,创建内部表外,绝大多数场景都是创建外部表。二、用户行为数据1、启动日志表ods_start_log//创建启动日志…

    2022年10月6日
    2
  • 关于tempdb的一些注意事项

    关于tempdb的一些注意事项

    2021年11月25日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号