Spring强大事务兼容数据库多种组合解决业务需求

目录
  • 事物的由来
    • 事物特性
    • 什么事脏读、不可重复读、幻读
    • 查询
  • spring事物
    • spring事物有哪些可配项
    • 传播属性

事物的由来

在mysql中只有innodb存储引擎才支持事物,所以我们后续都是基于innodb来展开的

事物特性

事物是用来保证数据的完整性的,保证批量sql执行的统一性;事物具有四个特性: A(Atomicity)、C(Consistency)、I(Isolation)、D(Durability)

原子性

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

一致性

在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

隔离性

数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。

持久性

事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

基于四个特性,我们就需要在数据和性能进行权衡,需要比较下场景。在m y s q l中就存在四种隔离级别。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read)
未提交读(Read uncommitted) 可能 可能 可能
已提交读(Read committed) 不可能 可能 可能
可重复读(Repeatable read) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能
  • 之前我一直错误的认为mysql中默认的是读已提交。后来查阅资料才知道默认的是可重复读隔离级别。

什么事脏读、不可重复读、幻读

上面提到了三种异常数据情况,作为一名合格的程序员我们需要知道不同的隔离级别会给我们造成具体什么样的伤害。

脏读

脏读指的是A事物在操作数据,还未进行提交此时B事物就已经感知到数据的变化了。这是我们最不能接受的。这里以个人举例,大学期间看中一款手机但是囊中羞涩需要爸妈支援下,打电话让爸妈赚钱这里我们理解成A事物,我着急用钱我是B事物,此时A事物向zxh这张表新增了money=5000元的一条数据。B事物在修改zxh这张表中money这个字段。如果我们是读未提交隔离级别。那么A事物刚新增完事物还未提交,B事物却已经可以修改了。那么B事物修改成功后就结束了。这个时候如果A事物因为别的原因出现异常了。那么就需要将add的5000进行回滚,回滚后余额出现负数。这个负数对于银行来说就是坏账。

#### 不可重复读

-   顾名思义就是同一条数据多次读取并不能保证数据一致性。这是因为A事物第一次读完数据后B事物修改了相同的数据行。那么A事物在此读取该数据就会发生不可重复读。

#### 幻读

-   不可重复读是针对同一条数据内容的变化。而幻读针对的是表记录的变化。还是A事物第一次查询数据匹配到10条,第二次相同条件匹配到的是20条。这就是幻读。
复制代码

查询

s q l 功能
select @@tx_isolation; 查询数据库默认隔离级别
select @@global.tx_isolation; 查看系统当前隔离级别
set session transaction isolation level repeatable read; 设置当前会话隔离级别
set global transaction isolation level repeatable read; 设置系统当前隔离级别
  • mysql 四种隔离级别对应关系 ; 设置时候去掉破折号就行了

REPEATABLE-READ

READ-COMMITTED

READ-UNCOMMITTED

SERIALIZABLE

  • 我们也可以通过show来查看相关配置
show variables like '%iso%';

spring事物

 @Override
 public Map<String, Object> startTransaction(Transmodel transmodel) {
   int insert = transMapper.insert(transmodel);
   log.info("操作日志:" + insert);
   if ("zxhtom".equals(transmodel.getName())) {
     throw new RuntimeException("error");
   }
   return new HashMap<>();
 }
复制代码
  • 上面代码逻辑非常的简单,当我们传送如下参数时就会报错
   {
     "name": "zxhtom",
     "code": "56",
     "age": 34
 }
复制代码
  • 但是呢?我们再去数据库查看,发现该数据进入数据库了。

  • 发生这种场景时不行的,在互联网中我们要求部分接口必须具有原子性,中途报错之前所有的操作就必须回滚。如果我们自己使用jdbc那么直接通过连接对象rollback就行了。
  • 在spring中因为连接session对接管了,我们就不必那么麻烦了,直接通过@Transactional标注我们的方法就可以实现事物了。
 @Transactional
 public Map<String, Object> startTransaction(Transmodel transmodel) {
   int insert = transMapper.insert(transmodel);
   log.info("操作日志:" + insert);
   if ("zxhtom".equals(transmodel.getName())) {
     throw new RuntimeException("error");
   }
   return new HashMap<>();
 }
复制代码
  • 在此执行就会发现,数据并没有新增,这就是我们想要的效果

spring事物有哪些可配项

  • 里面有几个属性我们需要关注下。已经圈出来了。

字段 作用
value 事物管理器;用于提交和回滚的功能;默认的DataSourceTransactionManager内部时datasource来操作提交回滚的
transactionManager 事物管理器;用于提交和回滚的功能;默认的DataSourceTransactionManager内部时datasource来操作提交回滚的
propagation 传播属性;spring中方法内方法事物传递属性设置
isolation 隔离级别,在数据库基础上新增一个默认以数据库隔离级别为准
timeout 超时事物不提交
readOnly 这个感觉没啥意义,被标注的方法无法执行更新操作,只能select
rollbackFor 导致事务回滚的异常类数组
rollbackForClassName 导致事务回滚的异常类名字数组
noRollbackFor 不会导致事务回滚的异常类数组
noRollbackForClassName 不会导致事务回滚的异常类名字数组

传播属性

  • 传播属性spring为我们建立了枚举
 public enum Propagation {
   REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
   SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
   MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
   REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
   NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
   NEVER(TransactionDefinition.PROPAGATION_NEVER),
   NESTED(TransactionDefinition.PROPAGATION_NESTED);
   private final int value;
   Propagation(int value) {
     this.value = value;
   }
   public int value() {
     return this.value;
   }
 }

以上就是Spring强大事务兼容数据库多种组合解决业务需求的详细内容,更多关于Spring事务解决业务需求的资料请关注我们其它相关文章!

(0)

相关推荐

  • spring在service层的方法报错事务不会回滚的解决

    目录 spring在service层方法报错事务不会回滚 解决方法 service手动回滚问题 spring在service层方法报错事务不会回滚 @Transactional(rollbackFor = {Exception.class}) public void insertData() throws Exception {     // 业务代码1     business1();          // 业务代码2     business2();          // 业务代码3  

  • springboot多个service互相调用的事务处理方式

    目录 多个service互相调用的事务处理 注解配置如下 Spring事务调用Service和Service之间的调用 原理解析 多个service互相调用的事务处理 今天,想在一个service的方法A中,调用另一个service的方法B,方法A和方法B均存在数据库插入操作,并且@Transaction注解也都加了,但是当B方法中抛出异常时,A中的插入语句还是能够执行成功. 注解配置如下 @Transactional(isolation= Isolation.DEFAULT,propagati

  • Spring Boot 多数据源处理事务的思路详解

    目录 1. 思路梳理 2. 代码实践 2.1 案例准备 2.2 开始整活 LoadDataSource.java 3. 总结 首先我先声明一点,本文单纯就是技术探讨,要从实际应用中来说的话,我并不建议这样去玩分布式事务.也不建议这样去玩多数据源,毕竟分布式事务主要还是用在微服务场景下. 好啦,那就不废话了,开整. 1. 思路梳理 首先我们来梳理一下思路. 在上篇文章中,我们是一个微服务,在 A 中分别去调用 B 和 C,当 B 或者 C 有一个执行失败的时候,就去回滚.B 和 C 都是调用远程的

  • 浅谈Spring嵌套事务是怎么回滚的

    目录 源码解析 TransactionAspectSupport.invokeWithinTransaction() 内层事务 TransactionAspectSupport.completeTransactionAfterThrowing() AbstractPlatformTransactionManager rollback() DataSourceTransactionManager#doSetRollbackOnly DataSourceTransactionObject#setRo

  • springboot编程式事务TransactionTemplate的使用说明

    目录 TransactionTemplate的使用 1.为何用? 2.如何用 TransactionTemplate简单使用 TransactionTemplate的使用 总结:在类中注入TransactionTemplate,即可在springboot中使用编程式事务. spring支持编程式事务管理和声明式事务管理两种方式. 编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager.对于编程式事务管理,spring推荐使用

  • Spring强大事务兼容数据库多种组合解决业务需求

    目录 事物的由来 事物特性 什么事脏读.不可重复读.幻读 查询 spring事物 spring事物有哪些可配项 传播属性 事物的由来 在mysql中只有innodb存储引擎才支持事物,所以我们后续都是基于innodb来展开的 事物特性 事物是用来保证数据的完整性的,保证批量sql执行的统一性:事物具有四个特性: A(Atomicity).C(Consistency).I(Isolation).D(Durability) 原子性 一个事务(transaction)中的所有操作,要么全部完成,要么全

  • 一篇文章带你了解spring事务失效的多种场景

    目录 前言 一 事务不生效 1.访问权限问题 2. 方法用final修饰 3.方法内部调用 4.未被spring管理 5.多线程调用 6.表不支持事务 7.未开启事务 二 事务不回滚 1.错误的传播特性 2.自己吞了异常 3.手动抛了别的异常 4.自定义了回滚异常 5.嵌套事务回滚多了 三 其他 1 大事务问题 2.编程式事务 总结 前言 对于从事java开发工作的同学来说,spring的事务肯定再熟悉不过了. 在某些业务场景下,如果一个请求中,需要同时写入多张表的数据.为了保证操作的原子性(要

  • Spring TransactionalEventListener事务未提交读取不到数据的解决

    目录 一.背景 二.问题分析 2.1.mysql隔离级别 2.2.问题原因分析 三.解决问题方案 3.1.方式一 3.2.方式二 四.使用案例 一.背景 业务处理过程,发现了以下问题,代码一是原代码能正常执行,代码二是经过迭代一次非正常执行代码 代码一:以下代码开启线程后,代码正常执行 ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS, new ArrayBlockingQ

  • Spring+SpringMVC配置事务管理无效原因及解决办法详解

    一般我们在Spring的配置文件application.xml中对Service层代码配置事务管理,可以对Service的方法进行AOP增强或事务处理如事务回滚,但是遇到一个问题,在Controller类中调用Service层方法,配置的事务管理会失效,查询相关资料发现原因.其实Spring和SpringMVC俩个容器为父子关系,Spring为父容器,而SpringMVC为子容器.也就是说application.xml中应该负责扫描除@Controller的注解如@Service,而Spring

  • 关于spring版本与JDK版本不兼容的问题及解决方法

    在用ssh框架测试时出现问题,如下: java.lang.IllegalArgumentException at org.springframework.asm.ClassReader.<init>(Unknown Source) at org.springframework.asm.ClassReader.<init>(Unknown Source) at org.springframework.asm.ClassReader.<init>(Unknown Sourc

  • 深入理解Spring的事务传播行为

    前言 Spring在TransactionDefinition接口中规定了7种类型的事务传播行为.事务传播行为是Spring框架独有的事务增强特性,他不属于的事务实际提供方数据库行为.这是Spring为我们提供的强大的工具箱,使用事务传播行可以为我们的开发工作提供许多便利.但是人们对他的误解也颇多,你一定也听过"service方法事务最好不要嵌套"的传言.要想正确的使用工具首先需要了解工具.本文对七种事务传播行为做详细介绍,内容主要代码示例的方式呈现. 基础概念 1. 什么是事务传播行

  • 基于spring 方法级缓存的多种实现

    方案实施 1. spring和ehcache集成 主要获取ehcache作为操作ehcache的对象. spring.xml中注入ehcacheManager和ehCache对象,ehcacheManager是需要加载ehcache.xml配置信息,创建ehcache.xml中配置不同策略的cache. <!-- ehCache 配置管理器 --> <bean id="ehcacheManager" class="org.springframework.ca

  • SuperSlide标签切换、焦点图多种组合插件

    此款插件包含在SuperSlide标签切换.焦点图多种组合插件,SuperSlide 是致力于实现网站统一特效调用的函数,能解决大部分标签切换.焦点图切换等效果,还能多个slide组合创造更多的效果.(兼容ie内核(包括无敌的 ie6).webkit内核.ff.opera等主流浏览器).适用于网站统一插件库其中包含了网站常用的大部分js效果.文件中包含使用详解. js调用: 复制代码 代码如下: jQuery(".slideTxtBox").slide( {effect:"l

  • Spring MVC实现mysql数据库增删改查完整实例

    最近刚学了springmvc框架,感觉确实方便了不少,减少了大量的冗余代码.就自己做了个小项目练练手,这是个初级的springmvc应用的项目,没有用到mybatis,项目功能还算完善,实现了基本的增删改查的功能. 项目环境: -系统:win10 -开发环境:eclipseOxygenReleaseCandidate3(4.7) -jdk版本:java1.8(121) -mysql:5.7 -spring:4.0 -tomcat:8.5 用到的技术: springmvcspringjspjdbc

  • Spring的事务机制实例代码

    本文研究的主要是Spring的事务机制的相关内容,具体如下. JAVA EE传统事务机制 通常有两种事务策略:全局事务和局部事务.全局事务可以跨多个事务性资源(即数据源,典型的是数据库和消息队列),通常都需要J2EE应用服务器的管理,其底层需要服务器的JTA支持.而局部事务则与底层采用的持久化技术有关,如果底层直接使用JDBC,需要用Connection对象来操事务.如果采用Hibernate持久化技术,则需要使用session对象来操作事务. 通常的,使用JTA事务,JDBC事务及Hibern

随机推荐