Java找工作必备知识——day05事务详解(小王,小刘情景在线解释事务的属性)

Posted 结构化思维wz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java找工作必备知识——day05事务详解(小王,小刘情景在线解释事务的属性)相关的知识,希望对你有一定的参考价值。

事务详解

一、事务

基本术语:

  • 事务(transaction)指一组 SQL 语句;
  • 回退(rollback)指撤销指定 SQL 语句的过程;
  • 提交(commit)指将未存储的 SQL 语句结果写入数据库表;
  • 保留点(savepoint)指事务处理中设置的临时占位符(placeholder),你可以对它发布回退(与回退整个事务处理不同)。

概念:

事务指的是满足ACID特性的一组操作,可以通过Commit提交一个事务,也可以使用RollBack进行回滚。

在这里插入图片描述

ACID

1️⃣ 原子性(Atomicity)

事务呗视为不可分割的最小单元,事务的所有操作,姚明明全部提交成功,要么全部是被回滚。

2️⃣ 一致性(Consistency)

数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对同一个数据的读取结果都是相同的。

3️⃣ 隔离性(Isolation)

一个事务所做的修改在最终提交以前,对其他事务是不可见的。

4️⃣ 持久性(Durability)

一旦事务提交,则起所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。

关系:

img

AutoCommit

mysql 默认采用自动提交模式。也就是说,如果不显式使用START TRANSACTION语句来开始一个事务,那么每个查询操作都会被当做一个事务并自动提交。

以上概念来自于github:cs_notes


二、事务属性详解

事务属性,就是描述事务特征的一系列值,就像描述人有身高体重等特征。

1.详解隔离属性

描述了事务解决并发问题的特征。

  • 什么是并发?

    多个事务(用户)在同一时间,访问操作了相同的数据

    • 同一时间:宏观的同一时间,有微小的前后。0.000几秒
  • 并发会产生哪些问题?

    • 脏读
    • 不可重复读
    • 幻影读
  • 并发如何解决?

    通过隔离属性解决,可以设置不同的值解决并发处理过程中的问题。

事务并发所产生的问题:

1️⃣ 脏读

一个事务读取了另一个事务中没有提交的数据。会在本事务中产生数据不一致的问题。

例子:小王跟小刘(小王媳妇),同时访问小王的银行卡。 共1000元。

👧 小刘要从小王的工资卡里取300块钱。这时候数据库肯定做更新操作(update(700))

👦 小王以0.0001秒的劣势也访问了工资卡,小王也要取钱,但是发现居然只有700块钱。于是就取了200块钱。这时候数据库(update500)

👧 小刘良心发现,觉得小王的私房钱已经够少了,决定不取了。这时候数据库rollback–>1000;

…晚上回家。

👨‍👧 : 小刘问小王,还有多少私房钱啊?看看是不是要再给小王一些零花钱。小王说:今天花了200,还有500了。 小刘大怒:什么?今天我看明明还有1000呢?你取200,另外三百呢???

👦 555555~ 跳进黄河也洗不清了。

通过本例,我们发现问题是,小王访问了小刘没有提交的数据。

💡 解决方案:**一个事务所做的修改在最终提交以前,对其他事务是不可见的。**读只能读已提交的数据!在spring中可以写@Transaction(Isonlation=Isonlation.READ_COMMITTED)

2️⃣ 不可重复读

一个事务中,多次读取相同的数据,但是读取结果不一样。会在本事务中产生数据不一致的问题。

例子:进过上次的教训,这次开启了事务。小王跟小刘并发访问银行卡数据。

👧 小刘以0.0001秒的优势先查了银行卡的余额。

👦 小王很快啊,取走200块钱,并且提交了事务。

👧 在事务还没提交的时候又做了其他操作,然后再看数据居然由1000变成了800。

这对小刘来说,出现了数据不一致的问题。而且800,不是脏数据,是已经提交的数据。

而且对小刘来说,是一次事务中发生的数据不一致!

💡 解决方案:隔离属性,加一把行锁。

小刘访问数据的时候被锁定了,小王就必须等小刘访问的事务结束。

在spring中可以写@Transaction(Isonlation=Isonlation.REPEATABLE_READ)

3️⃣ 幻影读

一个事务中,多次对整表进行查询统计,但是结果不一样,会在本事务中产生数据不一致的问题。

例子:一个事务访问一张表,并且统计数据。另一个事务插入了数据并且提交,这时候前面的事务统计数据就会不一致。

💡 解决方案:对应数据库底层的表锁

在spring中可以写@Transaction(Isonlation=Isonlation.SERIALIZABLE)

总结:

# 并发安全:表锁>行锁>READE_COMMITED

# 运行效率:表锁<行锁<READE_COMMITED

spring中默认的隔离属性:

Isonlation.DEFAULT 会调用不同数据库设置的默认隔离属性。

MYSQL:默认有行锁

Oracle:默认READE_COMMITED

select @@transaction_isolation; --mysql中查看默认隔离属性

隔离属性在实战中的建议:

推荐使用spring指定的ISOLATION_DEFAULT

并发概率低,没必要加很多锁来降低效率;如果真的遇到并发问题,我们更倾向于使用乐观锁,而不是物理锁的隔离属性。

mybatis没有自带乐观锁,可以使用自定义拦截器。

2.详解传播属性

描述了事务嵌套问题的特征。大事务中包含许多小事务。

Service调用service的特殊情况,有可能出现事务嵌套。

在这里插入图片描述

事务嵌套过程中,一旦某个出错,就会导致丧失了原子性

传播属性的值及其对应用法

传播属性的值外部不存在事务外部存在事务用法备注
REQUIRED开启新的事务融合到外部事务中@Transactional(propagation = Propagation.REQUIRED)增删改方法
SUPPORTS不开启事务融合到外部事务中@Transactional(propagation = Propagation.SUPPORTS)查询方法
REQUIRES_NEW开启新的事务挂起外部事务,创建新的事务@Transactional(propagation = Propagation.REQUIRES_NEW)日志记录方法中
NOT_SUPPORTED不开启事务挂起外部事务@Transactional(propagation = Propagation.NOT_SUPPORTED)及其不常用
NEVER不开启事务抛出异常@Transactional(propagation = Propagation.NEVER)及其不常用
MANDATORY抛出异常融合到外部事务中@Transactional(propagation = Propagation.MANDATORY)

默认的传播属性

REQUIRED是传播属性的默认值

推荐传播属性的使用方式

增删改 方法:直接使用默认值REQUIRED
查询 操作:显示指定传播属性的值为SUPPORTS

3.只读属性

针对于只进行查询操作的业务方法,可以加入只读属性,提供运行效率

默认值:false 

4.超时属性

指定了事务等待的最长时间

1. 为什么事务进行等待?
   当前事务访问数据时,有可能访问的数据被别的事务进行加锁的处理,那么此时本事务就必须进行等待。
2. 等待时间 秒
3. 如何应用 @Transactional(timeout=2)
4. 超时属性的默认值 -1 
   最终由对应的数据库来指定

5. 异常属性

Spring事务处理过程中
默认 对于RuntimeException及其子类 采用的是回滚的策略
默认 对于Exception及其子类 采用的是提交的策略

rollbackFor = {java.lang.Exception,xxx,xxx} 
noRollbackFor = {java.lang.RuntimeException,xxx,xx}

@Transactional(rollbackFor = {java.lang.Exception.class},noRollbackFor = {java.lang.RuntimeException.class})

建议:实战中使用RuntimeExceptin及其子类 使用事务异常属性的默认值

三、事务属性常见配置总结

1. 隔离属性   默认值 
2. 传播属性   Required(默认值) 增删改   Supports 查询操作
3. 只读属性   readOnly false  增删改   true 查询操作
4. 超时属性   默认值 -1
5. 异常属性   默认值 

增删改操作   @Transactional
查询操作     @Transactional(propagation=Propagation.SUPPORTS,readOnly=true)

以上是关于Java找工作必备知识——day05事务详解(小王,小刘情景在线解释事务的属性)的主要内容,如果未能解决你的问题,请参考以下文章

Java找工作必备知识——day02操作系统必备知识

Java找工作必备知识——day04万字SQL复习

Java找工作必备知识——day03MySQL索引原理

创建servlet程序知识点详解---servlet-day05

Java并发系列终结篇:学校门口保安小王,这次彻底搞懂了Java线程池的工作原理

含泪狂刷Java基础面试118题,附架构师必备技术详解