就这?一篇文章让你读懂 Spring 事务
什么是事务
▲ 百度百科
概括来讲,事务是一个由有限操作集合组成的逻辑单元。事务操作包含两个目的,数据一致以及操作隔离。数据一致是指事务提交时保证事务内的所有操作都成功完成,并且更改永久生效;事务回滚时,保证能够恢复到事务执行之前的状态。操作隔离则是指多个同时执行的事务之间应该相互独立,互不影响。
靓仔和小明的银行账户都有1000元,靓仔要给小明转账500元。
这个过程看似简单,实际上涉及了一系列的数据库操作,可以简单地视为两步基本操作,即从靓仔帐户的金额中扣除500元,以及将小明帐户中金额添加500元。
假设第一步数据库操作成功,第二步失败了,那就会出现小明账户金额没变,靓仔却白白少了500元的情况,靓仔岂不是很悲催。
事务机制可以避免此类情况,以保证整个操作的完成,如果某步操作出错,之前所做的数据库操作将全部失效。
事务的特性
提到事务,不可避免需要涉及到事务的四个特性(ACID):
- 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
- 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
- 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
- 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。
我们将严格遵循 ACID 属性的事务称为刚性事务。与之相对,期望最终一致性,在事务执行的中间状态允许暂时不遵循 ACID 属性的事务称为柔性事务,柔性事务的使用涉及到分布式事务方案,后续将为大家扩展,这里就不过多阐述。
Spring 事务管理的方式
1、编程式事务管理
编程式事务管理是侵入性事务管理,可通过 PlatformTransactionManager 实现来进行事务管理,Spring 提供了模板类 TransactionTemplate 进行事务管理。
2、声明式事务管理
声明式事务管理建立在 AOP 之上,有两种常用的方式,一是基于 tx 和 aop 命名空间的 xml 配置文件,一是基于 @Transactional 注解,随着 Spring 和 Java 的版本越来越高,越趋向于使用注解的方式。
其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,执行完目标方法之后根据执行的情况提交或者回滚。
声明式事务属于无侵入式,不会影响业务逻辑的实现,只需要在配置文件中做相关的事务规则声明或者通过注解的方式,便可以将事务规则应用到业务逻辑中。而编程式事务每次实现都要单独实现,但业务量大功能复杂时,使用编程式事务无疑是痛苦的。
显然声明式事务管理比编程式事务管理更可取,尽管它不如编程式事务管理灵活,这正是 Spring 倡导的非侵入式的编程方式。
顺便了解下注解 @Transactional 的作用范围:
- 方法 :推荐将注解使用于方法上,不过需要注意的是:该注解只能应用到 public 方法上,否则不生效。
- 类 :如果这个注解使用在类上的话,表明该注解对该类中所有的 public 方法都生效。
- 接口 :不推荐在接口上使用。
Spring 事务管理的五大属性
1、事务的隔离级别
当有多个事务同时执行时,就可能出现下面这些问题:
- 脏读:一个事务读取了另一个事务未提交的数据。
- 不可重复读:一个事务先后读取相同的数据,发现两次读取的数据内容不一致。
- 幻读:一个事务按相同的查询条件重新读取以前检索过的数据,却发现其它事务插入了满足其查询条件的新数据
而事务的隔离级别就定义了并发事务活动影响的程度。
ISOLATION_DEFAULT:使用后端数据库默认的隔离级别(MySQL 默认采用的REPEATABLE_READ 隔离级别 Oracle 默认采用的 READ_COMMITTED 隔离级别)
ISOLATION_READ_UNCOMMITTED:允许读取尚未提交的更改,这是最低的隔离级别,很少会使用。可能导致脏读、幻读或不可重复读。
ISOLATION_READ_COMMITTED:允许从已经提交的并发事务读取。可防止脏读,但幻读和不可重复读仍可能会发生。
ISOLATION_REPEATABLE_READ:对相同字段的多次读取的结果是一致的,除非数据被当前事务本身改变。可防止脏读和不可重复读,但幻读仍可能发生。
ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这在所有隔离级别中也是性能最差的,因为它通常是通过完全锁定当前事务所涉及的数据表来完成的。通常情况下也不会用到该级别。
2、事务的传播机制
事务的传播机制是为了解决事务嵌套的场景下,如何处理事务的问题。
PROPAGATION_REQUIRED(默认):
- 如果该方法执行在没有事务的方法中,就创建一个新的事务。
- 如果执行在已经存在事务的方法中,则加入到这个事务中,合并成一个事务。
PROPAGATION_SUPPORTS:
- 如果该方法执行在没有事务的方法中,就以非事务方式执行。
- 如果执行在已经存在事务的方法中,则加入到这个事务中,合并成一个事务。
PROPAGATION_MANDATORY:
- 如果该方法执行在没有事务的方法中,就抛出异常。
- 如果执行在已经存在事务的方法中,则加入到这个事务中,合并成一个事务。
PROPAGATION_REQUIRES_NEW:
- 无论该方法是否执行在事务的方法中,都创建一个新的事务。
- 不过如果执行在存在事务的方法中,就将方法中的事务暂时挂起。
- 新的事务会独立提交与回滚,不受调用它的父方法的事务影响。
PROPAGATION_NOT_SUPPORTED:
- 无论该方法是否执行在事务的方法中,都以非事务方式执行。
- 不过如果执行在存在事务的方法中,就将该事务暂时挂起。
PROPAGATION_NEVER:
- 如果该方法执行在没有事务的方法中,就也以非事务方式执行。
- 不过如果执行在存在事务的方法中,就抛出异常。
PROPAGATION_NESTED:
- 如果该方法执行在没有事务的方法中,就创建一个新的事务。
- 如果执行在已经存在事务的方法中,则在当前事务中嵌套创建子事务执行。
- 被嵌套的事务可以独立于封装事务进行提交或回滚。
- 如果外部事务提交嵌套事务也会被提交,如果外部事务回滚嵌套事务也会进行回滚。
3、只读
如果一个事务只包含了对数据库查询操作,那么可以利用事务的只读特性,将事务类型指定为 readonly 。只读事务下,数据库会进行一些优化。
有同学可能会问了,为什么查询操作还要加事务?
例如在做统计查询或者报表查询这样的场景下,可能会涉及多个查询,多条查询 SQL 必须保证整体的读一致性,否则,在前一条 SQL 查询之后,后一条 SQL 查询之前,数据被其他用户改变,那么这次整体的统计查询将会出现读数据不一致的状态,此时,就应该启用事务支持。
4、事务超时
事务超时指的是一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,就会自动回滚事务,避免长时间运行的事务会不必要地占用数据库资源。
5、回滚规则
默认情况下,事务只在出现运行时异常(runtime exception)时回滚,Error 也会导致事务回滚,但是在出现受检查异常(checked exception)时不回滚。
不过,可以声明在出现特定受检查异常时像运行时异常一样回滚。同样,也可以声明一个事务在出现特定的异常时不回滚,即使特定的异常是运行时异常。
总结
以上就是靓仔对 Spring 事务的理解,如有不足,也欢迎朋友们指正。
后面将会为大家介绍事务失效的几大场景,以及解决方案,敬请期待!
往期推荐
▼更多精彩推荐,请关注靓仔▼
就这?一篇文章让你读懂 Spring 事务的更多相关文章
- 一篇文章让你读懂Pivotal的GemFire家族产品
一篇文章让你读懂Pivotal的GemFire家族产品 学习了:https://www.sohu.com/a/217157517_747818
- 一篇文章教你读懂Makefile
makefile很重要 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professiona ...
- 一篇文章带您读懂List集合(源码分析)
今天要分享的Java集合是List,主要是针对它的常见实现类ArrayList进行讲解 内容目录 什么是List核心方法源码剖析1.文档注释2.构造方法3.add()3.remove()如何提升Arr ...
- 一篇文章让你读懂 OpenStack 的起源、架构和应用
OpenStack 是一个面向 IaaS 层的开源项目,用于实现公有云和私有云的部署及管理.拥有众多大公司的行业背书和数以千计的社区成员, OpenStack 被看作是云计算的未来.目前 OS 基金会 ...
- 一篇文章教你读懂UI绘制流程
最近有好多人问我Android没信心去深造了,找不到好的工作,其实我以一个他们进行回复,发现他们主要是内心比较浮躁,要知道技术行业永远缺少的是高手.建议先阅读浅谈Android发展趋势分析,在工作中, ...
- 一篇文章让你读懂iOS和Android的历史起源
智能手机虽说是移动电话,但我们完全可以将其作为小型化的电脑来思考.这样一来也能够显示出智能手机OS的高性能.我们首先一起来回顾下智能手机OS的历史. OS的黎明期 其实在很早之前就已经有这样的想法,即 ...
- 一篇文章带您读懂Map集合(源码分析)
今天要分享的Java集合是Map,主要是针对它的常见实现类HashMap进行讲解(jdk1.8) 什么是Map核心方法源码剖析1.文档注释2.成员变量3.构造方法4.put()5.get() 什么是M ...
- 五分钟学Java:一篇文章带你搞懂spring全家桶套餐
原创声明 本文首发于微信公众号[程序员黄小斜] 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 什么是Spring,为什么你要学习spring? 你第一次接触spring框架是在 ...
- 这一次搞懂Spring事务注解的解析
前言 事务我们都知道是什么,而Spring事务就是在数据库之上利用AOP提供声明式事务和编程式事务帮助我们简化开发,解耦业务逻辑和系统逻辑.但是Spring事务原理是怎样?事务在方法间是如何传播的?为 ...
随机推荐
- python应用_读取Excel数据【二】_二次封装之函数式封装
目的:想要把对Excel文件读取做成一个通用的函数式封装,便于后续简单调用,隔离复杂性. 未二次封装前原代码: #coding=gbkimport osimport xlrdcurrent_path= ...
- 使用IDEA创建Maven项目
一.创建一个普通的Maven项目 1.启动IDEA 2.创建一个Maven项目 3.Maven的目录结构 二.使用模板创建一个MavenWeb项目 1.启动IDEA 2.创建一个MavenWeb项目 ...
- 使用有道云笔记还是github写笔记的优缺点对比
有道云笔记的优点 在手机上编辑笔记,有道云的体验更好,建议:新建普通类型笔记而不是markdown笔记,因为md在手机上的编辑体验并不好 插入图片方便无需考虑图床 可以把笔记分享到社交平台(QQ,微信 ...
- P1045 [NOIP2003 普及组] 麦森数
题目描述 形如2^P−1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2^P−1不一定也是素数. 到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377, ...
- Java持久层框架Mybatis入门
MyBatis是什么 MyBatis是Java的持久层框架,GitHub的star数高达15.8k,是Java技术栈中最热门的ORM框架之一.它支持自定义SQL.存储过程以及高级映射,可以通过XML或 ...
- 打开黑盒:从 MySQL架构设计出发,看它是如何执行一条 SQL语句的
1.把MySQL当个黑盒子一样执行SQL语句 我们的系统采用数据库连接池的方式去并发访问数据库,然后数据库自己其实也会维护一个连接池,其中管理了各种系统跟这台数据库服务器建立的所有连接 当我们的系统只 ...
- 简述MSTP与配置
一.简介 二.MSTP概述 三.功能 四.配置命令 一.简介 多生成树协议MSTP(Multiple Spanning Tree Protocol)是IEEE 802.1s中定义的生成树协议,通过生成 ...
- 浙江大学计算机程序设计能力考试(PAT)简介
计算机程序设计能力考试(Programming Ability Test,简称 PAT)旨在通过统一组织的在线考试及自动评测方法客观地评判考生的算法设计与程序设计实现能力,科学地评价计算机程序设计人才 ...
- 收集雪花(map)
题目描述 不同的雪花往往有不同的形状.在北方的同学想将雪花收集起来,作为礼物送给在南方的同学们.一共有n个时刻,给出每个时刻下落雪花的形状,用不同的整数表示不同的形状.在收集的过程中,同学们不希望有重 ...
- 字节跳动实习面经分享(已拿offer附攻略)
大家好,我是bigsai,今天给大家分享自己字节跳动面试经验分享. enum我面得岗位是后台实习开发,具体部门是懂车帝,总体感觉就是字节的流程真的好快,只要安排面试,那流程接着很快. 大概是上上周投递 ...