什么是事务

▲ 百度百科

概括来讲,事务是一个由有限操作集合组成的逻辑单元。事务操作包含两个目的,数据一致以及操作隔离。数据一致是指事务提交时保证事务内的所有操作都成功完成,并且更改永久生效;事务回滚时,保证能够恢复到事务执行之前的状态。操作隔离则是指多个同时执行的事务之间应该相互独立,互不影响。

靓仔和小明的银行账户都有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 的作用范围:

  1. 方法 :推荐将注解使用于方法上,不过需要注意的是:该注解只能应用到 public 方法上,否则不生效。
  2. 类 :如果这个注解使用在类上的话,表明该注解对该类中所有的 public 方法都生效。
  3. 接口 :不推荐在接口上使用。

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 事务的理解,如有不足,也欢迎朋友们指正。

后面将会为大家介绍事务失效的几大场景,以及解决方案,敬请期待!

往期推荐

最详细的图文解析Java各种锁(终极篇)

SpringBoot+Redis 实现消息订阅发布

什么?你还不会在GitHub上搜索资源?还不点进来看看?

一定要收藏的5个优秀的SpringCloud开源项目

一定要收藏的5个后台管理系统的前端框架

▼更多精彩推荐,请关注靓仔▼

就这?一篇文章让你读懂 Spring 事务的更多相关文章

  1. 一篇文章让你读懂Pivotal的GemFire家族产品

    一篇文章让你读懂Pivotal的GemFire家族产品 学习了:https://www.sohu.com/a/217157517_747818

  2. 一篇文章教你读懂Makefile

    makefile很重要      什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professiona ...

  3. 一篇文章带您读懂List集合(源码分析)

    今天要分享的Java集合是List,主要是针对它的常见实现类ArrayList进行讲解 内容目录 什么是List核心方法源码剖析1.文档注释2.构造方法3.add()3.remove()如何提升Arr ...

  4. 一篇文章让你读懂 OpenStack 的起源、架构和应用

    OpenStack 是一个面向 IaaS 层的开源项目,用于实现公有云和私有云的部署及管理.拥有众多大公司的行业背书和数以千计的社区成员, OpenStack 被看作是云计算的未来.目前 OS 基金会 ...

  5. 一篇文章教你读懂UI绘制流程

    最近有好多人问我Android没信心去深造了,找不到好的工作,其实我以一个他们进行回复,发现他们主要是内心比较浮躁,要知道技术行业永远缺少的是高手.建议先阅读浅谈Android发展趋势分析,在工作中, ...

  6. 一篇文章让你读懂iOS和Android的历史起源

    智能手机虽说是移动电话,但我们完全可以将其作为小型化的电脑来思考.这样一来也能够显示出智能手机OS的高性能.我们首先一起来回顾下智能手机OS的历史. OS的黎明期 其实在很早之前就已经有这样的想法,即 ...

  7. 一篇文章带您读懂Map集合(源码分析)

    今天要分享的Java集合是Map,主要是针对它的常见实现类HashMap进行讲解(jdk1.8) 什么是Map核心方法源码剖析1.文档注释2.成员变量3.构造方法4.put()5.get() 什么是M ...

  8. 五分钟学Java:一篇文章带你搞懂spring全家桶套餐

    原创声明 本文首发于微信公众号[程序员黄小斜] 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 什么是Spring,为什么你要学习spring? 你第一次接触spring框架是在 ...

  9. 这一次搞懂Spring事务注解的解析

    前言 事务我们都知道是什么,而Spring事务就是在数据库之上利用AOP提供声明式事务和编程式事务帮助我们简化开发,解耦业务逻辑和系统逻辑.但是Spring事务原理是怎样?事务在方法间是如何传播的?为 ...

随机推荐

  1. 手把手教你彻底理解MySQL的explain关键字

    数据库是程序员必备的一项基本技能,基本每次面试必问.对于刚出校门的程序员,你只要学会如何使用就行了,但越往后工作越发现,仅仅会写sql语句是万万不行的.写出的sql,如果性能不好,达不到要求,可能会阻 ...

  2. NEXTCLOUD 常见错误

    HTTP请求头"Strict-Transport-Security"没有配置为至少"15552000"秒出于增强安全性考虑推荐按照安全提示中的说明启用HSTS ...

  3. 惊呆了,Spring Boot居然这么耗内存!

    Spring Boot总体来说,搭建还是比较容易的,特别是Spring Cloud全家桶,简称亲民微服务,但在发展趋势中,容器化技术已经成熟,面对巨耗内存的Spring Boot,小公司表示用不起.如 ...

  4. Shiro安全框架「快速入门」就这一篇

    Shiro 简介 照例又去官网扒了扒介绍: Apache Shiro is a powerful and easy-to-use Java security framework that perfor ...

  5. 【TCP/IP】TCP详解笔记

    目录 前言 17. TCP 传输控制协议 17.1 引言 17.2 TCP 服务 17.3 TCP的首部 18. TCP连接的建立与终止 18.1 引言 18.2 连接的建立与终止 18.2.1 建立 ...

  6. CosId 通用、灵活、高性能的分布式 ID 生成器

    CosId 通用.灵活.高性能的分布式 ID 生成器 介绍 CosId 旨在提供通用.灵活.高性能的分布式系统 ID 生成器. 目前提供了俩大类 ID 生成器:SnowflakeId (单机 TPS ...

  7. sql数据库新建作业,新建步骤时报错从 IClassFactory 为 CLSID 为 {AA40D1D6-CAEF-4A56-B9BB-D0D3DC976BA2} 的 COM 组件创建实例失败,原因是出现以下错误: c001f011。 (Microsoft.SqlServer.ManagedDTS)

    简单粗暴的重启sql数据库 其他网上找的方法 32位操作系统: 打开运行(命令提示符), 一.输入 cd c:\windows\system32 进入到c:\windows\system32路径中 二 ...

  8. 手摸手,带你用Beego撸商城系列一(基础篇)

    完整项目地址: go-shop-b2c 系列文章: 手摸手,带你用 Beego撸商城 系列一(基础篇) 手摸手,带你用 Beego撸商城 系列二(登录篇) 手摸手,带你用 Beego撸商城 系列三(系 ...

  9. 12.QT项目中启用c++11语法支持

    greater Than(QT_MAJOR_VERSION, 4): CONFIG += c++11 less Than(QT_MAJOR_VERSION, 5): QMAKE_CXXFLAGS += ...

  10. C# 小知识点记录

    1.当计算数据有小数点时不要使用float和double类型的数据,使用这两个会计算不准确.使用decimal 2.如果使用decimal计算数据,遇到除不进的数据有很多小数点的时候,在计算结果后面接 ...