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

一周深扒事务再也不怕面试官了问事务了全面解析

事务

  • 前言
  • 文章内容简介
  • 事务(理论) ⭐️⭐️⭐️⭐️
    • 什么是事务⭐️⭐️⭐️⭐️
    • 事务是怎么实现的(理论) ⭐️⭐️⭐️⭐️⭐️
    • 事务和AOP的关系
    • 代码解读 ⭐️⭐️⭐️⭐️⭐️
  • 简单使用事务
    • 开始测试
      • 1. 执行出现异常是否回滚
        • 🤔: 执行结果
      • 2. 下面情况事务会不会生效
        • 🤨:看一下控制台
        • 🤔: 查看数据库
      • 3. 下面事物会不会生效
        • 数据库
      • 阶段总结
    • 详细解析
      • Case 1: 类内部访问
        • 1. 调用方不进行事物控制 被调用方进行事物控制
        • 控制台
        • 数据库
      • 源码解析
        • 解释图
        • 源码:
        • 详细解读
        • 小总结
      • Case2: Private 事务失效
        • 简单解读:
        • 小总结
      • Case3 : 异常不匹配
        • 第一种情况
        • 第二种情况
        • 小总结
      • Case 4: 多线程事务失效
        • 代码演示
        • 小总结

前言

首先 作为一个开发 我们首先就是要保证数据的安全性和准确性 减少数据偏差 因为一点的数据偏差也可能造成 很大的事故 所以了解事务的正确使用是必备的 我们可能都知道什么是事务 事务的理论 ACID 随时都可以说出来 (如果不能立马在脑子里背出来就更要学习了) 其实在日常使用中 我们最重要的就是看事务是否生效 而不是加上事务就算完事了 循循渐进的去了解

文章内容简介

在这里插入图片描述

事务(理论) ⭐️⭐️⭐️⭐️

比较了解的可以直接跳过这一趴

什么是事务⭐️⭐️⭐️⭐️

事务具有四个特性:
原子性(Atomicity)

一致性(Consistency)

隔离性(Isolation)

持续性(Durability)

这四个特性也简称ACID。
原子性:

一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

就像你买东西要么交钱收货一起都执行,要么要是发不出货,就退钱。(最小了,不可再分了)

一致性:

事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态,这个是在原子性的基础上

隔离性:

指的是在并发环境中,相互隔离 ,互不干扰,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。(只能吃自己碗里的 不能吃别人碗里的 各吃各的)

持续性:
指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。

具体定义
事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元,组成事务的所有操作只有在所有操作均能正常执行的情况下方能提交,只要其中任一操作执行失败,都将导致整个事务的回滚。简单地说,事务提供一种“要么什么都不做,要么做全套(All or Nothing)”机制

事务是怎么实现的(理论) ⭐️⭐️⭐️⭐️⭐️

而事务的ACID是通过InnoDB日志和锁来保证。事务的隔离性是通过数据库锁的机制实现的,持久性通过redo log(重做日志)来实现,原子性和一致性通过Undo log来实现。UndoLog的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为UndoLog)。然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。
和Undo Log相反,RedoLog记录的是新数据的备份。在事务提交前,只要将RedoLog持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是RedoLog已经持久化。系统可以根据RedoLog的内容,将所有数据恢复到最新的状态。

事务和AOP的关系

我们都知道AOP 的一个功能 就是事务所以AOP 和 Transaction 之间的关系是很密切的 说白了就是 事务就是由AOP 动态代理去处理的 也影响着事务是否生效 下面通过源码可以看出两者之间的关系

代码解读 ⭐️⭐️⭐️⭐️⭐️

简单使用事务

前期准备工作

  • 数据库表结构

在这里插入图片描述

开始测试

1. 执行出现异常是否回滚

加上事务 @Transactional注解 开启这个方法的事务监控 name 我们数据设定的是不能为空 我们进行置空 这个时候肯定回出现错误
这个时候第一个插入不会出错 第二个插入出错这个时候事务会生效吗 ?

![在这里插入图片描述](https://img-blog.csdnimg.cn/c13209e4bdbb4282af00dc8fa91cdd00.png

🤔: 执行结果

如果这个时候不生效 的话 这个事务注解也没什么作用了 所以 事务是生效的 数据库无数据
在这里插入图片描述

2. 下面情况事务会不会生效

我们在Insert 之后手动抛出错误 这个时候 那么事务会不会回滚呢? 心中想一下答案

    @Override
    @Transactional
    public void affairsExamination(Affairs affairs) throws Exception {
        affairsMapper.insert(affairs);
       throw new Exception("出现错误");
    }
}

🤨:看一下控制台

在这里插入图片描述
错误准时出现 sql 语句也执行了 那么数据有数据吗?

🤔: 查看数据库

在这里插入图片描述

这个时候数据出现数据 为什么出现错误事务没有回滚呢

只要原因是 @Transaction 默认只会在遇到RuntimeException的时候才会回滚 也就是运行时异常才会回滚 非运行时异常不会回滚 上述异常 为非运行时异常所以事务不会进行回滚处理
在这里插入图片描述
虽然 SQLException 是非运行时异常 但是因为在同一个事物下面所以事务还是会回滚
在这里插入图片描述

3. 下面事物会不会生效

同样是自自定义抛出错误 加上红框框里的内容事物会不会回滚
在这里插入图片描述
数据库 数据为空 数据回滚 rollbackFor = Exception.class这个就是无论 运行时异常还是 非运行时异常 只要是Exception下的都进行回滚。可以在使用事物的时候加上

数据库

在这里插入图片描述

阶段总结

  • @Transactional 默认只能回滚运行时异常
  • @Transactional(rollbackFor = Exception.class) 可以回滚 Exception下面的子类异常

详细解析

Case 1: 类内部访问

1. 调用方不进行事物控制 被调用方进行事物控制

这个时候我们抛出自定义 事务是否会回滚
在这里插入图片描述

控制台

在这里插入图片描述

数据库

在这里插入图片描述
如期报错 但是 数据添加成功 事物没有生效

源码解析

解释图

在这里插入图片描述
因为 @Transactional 的工作机制是基于 AOP 实现,AOP 是使用动态代理实现的,如果通过代理直接调用 insertData(),通过 AOP 会前后进行增强,增强的逻辑其实就是在 insertData() 的前后分别加上开启、提交事务的逻辑。

源码:

在这里插入图片描述
在这里插入图片描述
个人感觉这里是分割点 决定事务是否生效 下面的几个 失效场景也会用到
在这里插入图片描述
在这里插入图片描述
比较明显的两个注解 Modifier.isPublic(method.getModifiers()) && method.getDeclaringClass() != Object.class 这就对应了下面的这句话 仅对不是从java.lang.Object 派生的公共代理使用
在这里插入图片描述

详细解读

篇幅过长 请跳转另一个博客查看 :链接: 深扒事务内部类调用失效

小总结

  1. 事务失效的原因主要是因为没有获取到拦截器链 没有通知的资格 也就是 AOP 不会对方法做什么增强 仅仅是单纯的方法调用

反过来: 🌟🌟🌟🌟🌟
调用方添加@Transaction 这个时候 事务会生效 因为时通过代理持有者直接调用 affairExamination 前后增加开启和提交事务的逻辑 所以事务就生效了
在这里插入图片描述
数据库无数据。出现异常事务回滚

Case2: Private 事务失效

首先这个会出现编译提示
翻译使用“@Transactional”注释的方法必须是可覆盖的
出现这种提示 你还接着用 那就挺离谱的 该挨批 private 这种几乎没有使用场景。直接探究一下为什么 @Transactional 在private修饰下会失效的问题🤯
在这里插入图片描述

简单解读:

我们简单看一下代码 上面如果你认真看了 就知道事务是否生效是和AOP 动态代理有关联的 当没有进行AOP 动态代理的增强事务就不会生效了 如图一所示 AOP 只会代理 公共方法
图一:在这里插入图片描述
会进行判断当前的修饰符是不是Public修饰的 。在这里插入图片描述
这里会进行判断 是 public 修饰的就返回true。不是就返回false
在这里插入图片描述

小总结

这个其实就是AOP的特性 :只需要记住一点 在用Aop切入方法时,注意方法的类型要设置成public共有类型! AOP 没办法切入 事务就是无效的

Case3 : 异常不匹配

这种有两种情况

第一种情况

看完上面应该知道 事务默认只能对运行时异常进行回滚 所以在使用 @Transactional 时没有增加 rollbackFor = Exception.class 导致出现异常 无法事务没有进行监听
在这里插入图片描述

点进rollbackOn 方法 发现 return ex instanceof RuntimeException || ex instanceof Error 这个都懂哈
返回false 就不执行回滚 直接就commit
在这里插入图片描述

第二种情况

异常捕获了。事务感知不到 所以在使用Try - catch 的时候注意
在这里插入图片描述

小总结

  1. 没有添加 rollbackFor = Exception.class 所以只能捕获运行时异常
  2. 不合理的Tty-catch 导致事务无法感知异常

Case 4: 多线程事务失效

代码演示

在这里插入图片描述
能走到这一步说明 子线程出现错误 对父线程没有影响 所以事务没有生效 有点想异常的第二种情况

小总结

由于子线程的异常不会被外部的线程捕获,所以父线程不抛异常,事务回滚没有生效。

相关文章:

  • 程序员是如何思考的?
  • 51. new 操作符的实现原理?
  • ArcGIS模拟风场(流场)
  • 【Pytorch】torch. bmm()
  • 并发编程模型
  • 使用Mindspore运行Resnet50Imagenet
  • 基于springboot+vue的在线作业管理考试系统 elementui
  • 07、Metasploit渗透测试框架的基本使用
  • DUBBO版本差异
  • 现在的数字藏品该怎么玩才不会被割韭菜?
  • LeetCode_双指针_中等_611.有效三角形的个数
  • 代理模式——静态代理和动态代理
  • 时域中的离散时间信号02—详解离散卷积
  • 一个Kbuild工程生成多个ko文件及其在驱动单元测试上的应用
  • 计算机毕业设计java毕业设计项目源代码精品SSM学生选课系统[包运行成功]
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • Angular2开发踩坑系列-生产环境编译
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • FastReport在线报表设计器工作原理
  • javascript 总结(常用工具类的封装)
  • MYSQL 的 IF 函数
  • QQ浏览器x5内核的兼容性问题
  • 安卓应用性能调试和优化经验分享
  • 大数据与云计算学习:数据分析(二)
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 前端相关框架总和
  • 使用 @font-face
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • 阿里云ACE认证之理解CDN技术
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (C语言)字符分类函数
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (十六)串口UART
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (四)Linux Shell编程——输入输出重定向
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (转)shell中括号的特殊用法 linux if多条件判断
  • .NET 使用 XPath 来读写 XML 文件
  • .Net语言中的StringBuilder:入门到精通
  • .sh文件怎么运行_创建优化的Go镜像文件以及踩过的坑
  • @Service注解让spring找到你的Service bean
  • @Transient注解
  • [ CTF ]【天格】战队WriteUp- 2022年第三届“网鼎杯”网络安全大赛(青龙组)
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • [ 云计算 | AWS 实践 ] Java 如何重命名 Amazon S3 中的文件和文件夹
  • [android] 练习PopupWindow实现对话框
  • [Android]Android开发入门之HelloWorld
  • [BROADCASTING]tensor的扩散机制