首页 > 其他 > 详细

初学事务

时间:2020-09-23 21:08:43      阅读:56      评论:0      收藏:0      [点我收藏+]

事务

  (一)什么是事务

    事务:是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元)。

      简单理解的事务:

            就是把一堆事情绑在一起做,都成功了才算完成,否则就恢复之前的样子 
    举例:银行ATM取钱,扣款成功后突然大停电,吐钱的操作还没做,这时候就要恢复没取钱时候的状态,否则钱扣了还没拿到手,多冤枉

 

  (二)事务的特性ACID

      1.Atomic(原子性):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成功,要么全部失败。

        比如在同一个事务中的SQL语句,要么全部执行成功,要么全部执行失败

      2.Consistency(一致性):只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初状态。

        官网上事务一致性的概念是:事务必须使数据库从一个一致性状态变换到另外一个一致性状态

    以转账为例子,AB转账,假设转账之前这两个用户的钱加起来总共是2000,那么AB转账之后,不管这两个账户怎么转,A用户的钱和B用户的钱加起来的总额还是2000,这个就是事务的一致性。

      3.Isolation(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。

      事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

      4.Durability(持久性):事务完成之后,它对于系统的影响是永久的,该修改即使出现系统故障也将一直保留,真实的修改了数据库。

(三)事务不考虑隔离性可能会引发的问题  

1.脏读

  脏读指一个事务读取了另外一个事务未提交的数据

      A事务读取B事务尚未提交的更改数据,并在这个数据的基础上进行操作,这时候如果事务B回滚,那么A事务读到的数据是不被承认的。

              例如常见的取款事务和转账事务: 

                                             技术分享图片

 

2.不可重复读

   不可重复读指在一个事务内读取表中的某一行数据,多次读取结果不同。
    例如银行想查询A帐户余额,第一次查询A帐户为200元,此时A向帐户内存了100元并提交了,银行接着又进行了一次查询,此时A帐户为300元了。银行两次查询不一致,可能就会很困惑,不知道哪次查询是准的。


    不可重复读和脏读的区别是,脏读是读取前一事务未提交的脏数据,不可重复读是重新读取了前一事务已提交的数据

3.虚读(幻读)

  虚读(幻读)是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致

        例如:银行系统在同一个事务中两次统计存款账户的总金额,在两次统计中,刚好新增了一个存款账户,存入了100,这时候两次统计的总金额不一致。 

                           技术分享图片

4.第一类丢失更新

  A事务撤销时,把已经提交的B事务的更新数据覆盖了。例如: 

 

  这时候取款事务A撤销事务,余额恢复为1000,这就丢失了更新

5.第二类丢失更新

  A事务覆盖B事务已经提交的数据,造成B事务所做的操作丢失 

 

 

(四)事务的隔离级别

 MySQL数据库共定义了四种隔离级别:

  1. Read uncommitted(读未提交):最低级别,以上情况均无法保证。
  2. Read committed(读已提交):可避免脏读情况发生。
  3. Repeatable read(可重复读):可避免脏读、不可重复读情况的发生。
  4. Serializable(串行化):可避免脏读、不可重复读、虚读情况的发生。

 

(五)@Transactional注解

@Transactional注解可以作用于接口、接口方法、类以及类方法上

  1.  @Transactional 注解只能应用到 public 可见度的方法上。 如果你在 protectedprivate 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错 但是这个被注解的方法将不会展示已配置的事务设置
  2. @Transactional 的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类一个方法调用另一个方法有事务的方法,事务是不会起作用的。
  3. @Transactional也是基于代理模式实现的,默认是jdk的,也可以修改为cglib
  4. @Transactional注解的方法中如果有trycatch代码块trycatch代码块出现异常不会进行自动回滚。可以通过      TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 手动回滚  

1.@Transactional 的属性

属性

描述

Value

可选的限定描述符,指定使用的事务管理器

Propagation

可选的事务传播行为设置默认值为REQUIRED

Isolation

可选的事务隔离级别设置默认值采DEFAULT

Read_Only

该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false

Timeout

事务超时时间设置 默认是30

 默认值设置-1表示永不超时

rollbackFor

该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。

rollbackForClassName

该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚

noRollbackFor

该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚

noRollbackForClassName

该属性用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚

2.Propagation事务传播行为

1.@Transactional(propagation=Propagation.REQUIRED) :

如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)

2.@Transactional(propagation=Propagation.NOT_SUPPORTED) :

容器不为这个方法开启事务

3. @Transactional(propagation=Propagation.REQUIRES_NEW) :

不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务

4. @Transactional(propagation=Propagation.MANDATORY) :

必须在一个已有的事务中执行,否则抛出异常

5.@Transactional(propagation=Propagation.NEVER) :

必须在一个没有的事务中执行,否则抛出异常(Propagation.MANDATORY相反)

6.@Transactional(propagation=Propagation.SUPPORTS) :

如果其他bean调用这个方法,在其他bean声明事务,就用事务.如果其他bean没有声明事务,就不用事务.

 

3.isolation该属性用于设置底层数据库的事务隔离级别

事务隔离级别介绍:

    1. @Transactional(isolation = Isolation.READ_UNCOMMITTED)读取未提交数据(会出现脏读, 不可重复读) 基本不使用
    2. @Transactional(isolation = Isolation.READ_COMMITTED)读取已提交数据(会出现不可重复读和幻读)
    3. @Transactional(isolation = Isolation.REPEATABLE_READ)可重复读(会出现幻读)
    4. @Transactional(isolation = Isolation.SERIALIZABLE)串行化

初学事务

原文:https://www.cnblogs.com/yanzhong/p/13720360.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!