事务

事务的特性(ACID)

原子性(Atomicity):

标识将事务中所有的操作进行捆绑层一个不可分割的单元格,
计对事务所有进行的数据库修改等操作,要么全部执行,要么就是全部失败
隔离性(Isolation):
指的是一个事务的执行,不能被其他的事务进行干扰,一个事务内部的操作以及使用的数据库对并发的其他事务都是进行隔离的,并发执行的各个事务之间是不能进行相互干扰的  事务之间隔离,互不干扰
持久性(Durability):
永久性,指一个事务提交之后,它对数据库中数据的改变应该是永久性的

一致性(Consistency):
事务前后,数据库数据完整性不被破坏,总是与预期一致的状态,就像借钱,一方借多少,另一方加多少,数据不会凭空增多,也不会凭空减少。

数据是一致且持久的,操作是原子且隔离的

事务的四种隔离级别

①read uncommitted(读未提交):事物的修改,即使没有提交,对其他事务也是可见的。事务读未提交的数据成为脏读。
②read committed(读已提交):只能读取到其他事务已经提交的数据。
③repeatable read(可重复读):该级别解决了脏读、不可重复读的问题,保证了在一个事物中多次读到的数据是一致的,但是没有解决幻读的问题。(默认)
④serializable(串行化):事务挨个执行,避免了幻读的问题。

数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上 “串行化”进行,这显然与“并发”是矛盾的

同时,不同的应用对读一致性和事务隔离程度的要求也是不同的,比如许多应用对“不可重复读”和“幻读”并不敏感,可能更关心数据并发访问的能力。

主流数据库默认的事务隔离级别

Mysql——repeatable read(可重复读)

Oracle——read committed(读已提交)

PostGreSql——read committed(读已提交)

事务并发可能产生的问题(不考虑隔离级别)

脏读

读到另一事务还未提交的数据。

(只有读未提交隔离级别才会出现这种问题 。 eg:A对数据减10但还未提交,B读取到的数据数据已经少了10)

不可重复度

一个事务多次对相同的数据读取可能会出现不同的结果

(读未提交和读已提交的隔离级别下都可能会出现不可重复读的问题,关键在于重复读取的数据同时在被其他事务进行修改操作)

幻读/虚读:

当前事务读取数据时,读范围内的数据,被其他事务穿插有修改操作,导致出现读取幻象。

(在读未提交、读已提交和可重复读三种事务隔离级别下都可能会出现)

Spring事务

Spring管理事务的方式

  • 编程式事务,在代码中硬编码。(不推荐使⽤)
  • 声明式事务,在配置⽂件中配置(推荐使⽤)
    •   基于XML的声明式事务
    •   基于注解的声明式事务

Spring事务五种隔离级别

一种控制并发执行的事务对数据操作的规则。

TransactionDefinition 接⼝中定义了五个表示隔离级别的常量

TransactionDefinition.ISOLATION_DEFAULT:  数据库默认

使⽤后端数据库默认的隔离级别,Mysql 默认采⽤的 REPEATABLE_READ隔离级别 Oracle 默认采⽤的 READ_COMMITTED隔离级别.

TransactionDefinition.ISOLATION_READ_UNCOMMITTED:  读未提交

最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

TransactionDefinition.ISOLATION_READ_COMMITTED:  读已提交

允许读取并发事务已经提交的数据,可以阻⽌脏读,但是幻读或不可重复读仍有可能发⽣

TransactionDefinition.ISOLATION_REPEATABLE_READ: 可重复读

对同⼀字段的多次读取结果都是⼀致的,除⾮数据是被本身事务⾃⼰所修改,可以阻⽌脏读和不可重复读,但幻读仍有可能发⽣。

TransactionDefinition.ISOLATION_SERIALIZABLE: 序列化

最⾼的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执⾏,这样事务之间就完全不可能产⽣⼲扰,也就是说,该

级别可以防⽌脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会⽤到该级别。

                                              --参考java Guide文章

Spring事务的7种传播行为

⽀持当前事务的情况:
TransactionDefinition.PROPAGATION_REQUIRED: 存在则加入,没有就新建

如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务。

TransactionDefinition.PROPAGATION_SUPPORTS:存在则加入,没有则不管

如果当前存在事务,则加⼊该事务;如果当前没有事务,则以⾮事务的⽅式继续运⾏。

TransactionDefinition.PROPAGATION_MANDATORY: 存在则加入,没有就抛异常

如果当前存在事务,则加⼊该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)

不⽀持当前事务的情况:
TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建新事物,存在则挂起

创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。

TransactionDefinition.PROPAGATION_NOT_SUPPORTED:非事务运行,存在则挂起

以⾮事务⽅式运⾏,如果当前存在事务,则把当前事务挂起。

TransactionDefinition.PROPAGATION_NEVER:非事务运行,存在则抛异常

以⾮事务⽅式运⾏,如果当前存在事务,则抛出异常。

其他情况:
TransactionDefinition.PROPAGATION_NESTED:存在则嵌套事务,没有就新建

如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运⾏;如果当前没有事务,则该取值等价TransactionDefinition.PROPAGATION_REQUIRED。

                                            --参考java Guide文章

Spring事务回滚rollbackFor

@Transactional(rollbackFor = Exception.class)

当 @Transactional 注解作⽤于类上时,该类的所有 public ⽅法将都具有该类型的事务属性,同时,我们也可以在⽅法级别使⽤该标注来覆盖类级别的定义。

一般用于方法级别。

如果类或者⽅法加了这个注解,那么这个类⾥⾯的⽅法抛出异常,就会回滚,数据库⾥⾯的数据也会回滚。

在 @Transactional 注解中如果不配置 rollbackFor 属性,那么事物只会在遇到 RuntimeException时候才会回滚,加上 rollbackFor=Exception.class ,可以让事物在遇到⾮运⾏时异常时也回滚。

场景验证

参考: https://blog.csdn.net/u014532775/article/details/106690766

Propagation.REQUIRED

在外围方法未开启事务的情况下Propagation.REQUIRED修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
在外围方法开启事务的情况下Propagation.REQUIRED修饰的内部方法会加入到外围方法的事务中,所有Propagation.REQUIRED修饰的内部方法和外围方法均属于同一事务,只要一个方法回滚,整个事务均回滚。
特别:对于下面这种捕获异常的,事务注解的方法已经抛出异常了,只是在方法外进行了捕获并不影响事务回滚 =》三个事务都会回滚
 @Transactional
@Override
public void transaction_required_required_exception_try(){
User1 user1=new User1();
user1.setName("张三");
user1Service.addRequired(user1); User2 user2=new User2();
user2.setName("李四");
try {
user2Service.addRequiredException(user2);
} catch (Exception e) {
System.out.println("方法回滚");
}
} @Service
public class User1ServiceImpl implements User1Service {
//省略其他...
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addRequired(User1 user){
user1Mapper.insert(user);
}
} @Service
public class User2ServiceImpl implements User2Service {
//省略其他...
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addRequired(User2 user){
user2Mapper.insert(user);
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void addRequiredException(User2 user){
user2Mapper.insert(user);
throw new RuntimeException();
}
}

PROPAGATION_REQUIRES_NEW

在外围方法未开启事务的情况下Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰

在外围方法开启事务的情况下Propagation.REQUIRES_NEW修饰的内部方法依然会单独开启独立事务,且与外部方法事务也独立,内部方法之间、内部方法和外部方法事务均相互独立,互不干扰。

Propagation.REQUIRES_NEW修饰方法抛出的异常在外部方法中如不捕获,会影响外部方法事务的回滚。

Spring事务方法套方法,内部事务方法不生效?

Spring事务用到代理,代理去对标记有@Transactional的方法开启事务startTransaction(),内部的调用是由被代理对象直接调用,不会再开启事务,因此内部事务不生效

解决办法,通常是将方法分别放在不同的service中

事务与spring事务的更多相关文章

  1. 数据库事务和spring事务的区别

    数据库事务和spring事务 本质上其实是同一个概念,spring的事务是对数据库的事务的封装,最后本质的实现还是在数据库,假如数据库不支持事务的话,spring的事务是没有作用的.数据库的事务说简单 ...

  2. 数据库程序接口——JDBC——功能第四篇——事务之Spring事务

    综述 事务的实现方式有三种,JTA,Spring事务,Web Container方式.本篇讲述Spring事务. Spring事务分为两个部分核心对象,Spring事务的实现方式. Spring事务实 ...

  3. hibernate的事务和spring事务的区别 (转)

    spring事务: 对于传统的基于特定事务资源的事务处理而言(如基于JDBC的数据库访问),Spring并不会对其产生什么影响,我们照样可以成功编写并运行这样的代码.同时,Spring还提供了一些辅助 ...

  4. MySQL事务及Spring事务管理

    事务,是在数据库中用于保证数据正确性的一种机制,涉及到很多概念以及不同的情况,这里做一个总结 相关概念 事务四特性(ACID) 原子性(Atomicity,或称不可分割性):要么全部完成或者全部不完成 ...

  5. 【声明式事务】Spring事务特性(二)

    spring所有的事务管理策略类都继承自org.springframework.transaction.PlatformTransactionManager接口. 其中TransactionDefin ...

  6. 【声明式事务】Spring事务介绍(一)

    事务管理对于企业应用来说是至关重要的,当出现异常情况时,它也可以保证数据的一致性. Spring事务有两种管理方式:编程式事务和声明式事务 编程式事务使用TransactionTemplate或者直接 ...

  7. 【Spring】Spring的事务管理 - 1、Spring事务管理概述(数据库事务、Spring事务管理的核心接口)

    Spring事务管理概述 文章目录 Spring事务管理概述 数据库事务 什么是Spring的事务管理? Spring对事务管理的支持 Spring事务管理的核心接口 Platform Transac ...

  8. spring事务传播机制实例讲解

    http://kingj.iteye.com/blog/1680350   spring事务传播机制实例讲解 博客分类:   spring java历险     天温习spring的事务处理机制,总结 ...

  9. 深入理解 Spring 事务原理

    本文由码农网 – 吴极心原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 一.事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供 ...

  10. spring 事务 笔记3.1

    Spring事务 以前的事务都是编程式事务,需要开启和关闭,然后程序写在这里面 spring,声明式事务 Spring事务隔离级别 DEFAULT 使用数据库默认隔离级别 READ_UNCOMMITT ...

随机推荐

  1. ctfshow_web入门 文件上传

    文件上传 还是是一边学习一边做笔记的文章,由于是学习,所以会显得啰嗦 还请各位师傅担待~ 如果有不正确的地方,请师傅们斧正谢谢师傅们 web150 火狐关闭js的插件一旦开启,就没法点击上传按钮了. ...

  2. 新一代自动化利器-DrissionPage

    熟悉的小伙伴知道我的工作有相当一部分是自动化,在探索相关的技术上一直没停下脚步,我痛恨selenium.playwright的非标准内核机制,也曾对clicknium引进了新的问题无语,以及接口爬取数 ...

  3. C# Socket 通信时,怎样判断 Socket 双方是否断开连接

    参考内容: C#socket通信时,怎样判断socket双方是否断开连接 C#之Socket断线和重连 Socket.Poll 方法 Socket.Blocking 属性 最近需要写个网口通信的上位机 ...

  4. JZOJ 1075. 【GDKOI2006】新红黑树

    \(\text{Problem}\) A君和B君在玩一种叫做新红黑树的游戏,即在一棵由红枝和黑枝构成的树上轮流砍树枝,每次砍一枝,A君每次只能砍红枝,B君每次只能砍黑枝,当其中某人已经没有树枝砍的时候 ...

  5. JZOJ 5432. 【NOIP2017提高A组集训10.28】三元组

    题目 有 \(X+Y+Z\) 个三元组 \((x[i],y[i],z[i])\),请你从每个三元组中挑数,并满足以下条件: 1.每个三元组中可以且仅可以选择一个数(即 \(x[i],y[i],z[i] ...

  6. JZOJ 5350. 【NOIP2017提高A组模拟9.7】陶陶摘苹果

    题目 分析 很神奇的事情又发生了!! 很容易想到设 \(f_{i,j}\) 表示考虑前 \(i\) 个区间,已选 \(j\) 个区间且必选第 \(i\) 时能覆盖到的最多苹果数 转移 \(O(n)\) ...

  7. 【6】java之数组的定义和使用

    一.数组的定义与使用 1.1 数组的基本概念 数组指的就是一组相关变量的集合. 数组的定义: 声明并开辟数组 数据类型 数组名称 [] = new 数据类型[长度]: 数据类型 [] 数组名称 = n ...

  8. 四种语言刷算法之删除链表的倒数第 N 个结点

    力扣19. 删除链表的倒数第 N 个结点 1.C /**  * Definition for singly-linked list.  * struct ListNode {  *     int v ...

  9. 马哥教育第一周作业N67044-张铭扬

    1. 图文并茂解释开源许可证 GPL.BSD.MIT.Mozilla.Apache和LGPL的区别? 1)MIT许可证:MIT是六种开源许可证中最自由宽容,它允许使用者自由修改后无需放置版权说明并且可 ...

  10. fabric学习笔记8

    fabric学习笔记8 20201303张奕博 2023.1.19 具体结构: Wallet中的X.509数字证书将组织和持有者联系起来,使得持有者能够有权限连接到网络,不同的持有者身份拥有不同的权限 ...