Spring学习日记【4】——事务、隔离性和@Transactional

事务、隔离性和@Transactional

什么是事务

事务主要是逻辑上的一组操作,主要是对数据库 i读/o写的操作,或是对数据库增删改查的操作。但并不是所有这样的操作都能称为事务:事务至少要包含以下四个特性:

  • 原子性:事务中的操作,要么全做成,要么都不做,事务是不可拆分的,事务必须是以commit和rollback结束。任何一项操作失败都将导致整个事务失败,同时其他已经被执行的操作都将被撤销并回滚,只打所有的操作全部成功,整个事务才算是成功完成。
  • 一致性:事务的一致性是指事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处于一致性状态。也就是说,事务执行的结果必须是使数据库从一个一致性状态转变到另一个一致性状态,因此当数据库只包含成功事务提交 的结果时,就能说数据库处于一致性状态。而如果数据库系统在运行过程中发生故障, 有些事务尚未完成就被迫中断,这些未完成的事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是不一致的状态。
  • 隔离性:事务的隔离性是指在并发环境中,并发的事务是相互隔离的,一个事务的执行不能被其他事务干扰。也就是说,不同的事务并发操纵相同的数据时,每个事务都有各自完整的数据空间,即一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的 各个事务之间不能互相干扰。
  • 持久性:一旦事务成功完成,commit它对数据库的更新操作是永久持久的,数据不会发生改变。

事务的隔离等级

因此,一方面,当多个应用程序并发访问数据库时,事务可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。另一方面,事务为数据库操作序列提供了一个从失败中恢复到正常状态的方法, 同时提供了数据库即使在异常状态下仍能保持数据一致性的方法。对于事务在隔离中仍然可能出现的问题,我们对事务仍然规定了隔离等级,随着隔离等级不断增强,可能由于隔离性不足而产生的问题也随之被避免,四种隔离等级由低到高为:

  1. 未授权读取
    未授权读取也被称为读未提交(Read Uncommitted),该隔离级别允许脏读取,其隔离级別最低。换句话说,如果一个事务正在处理某一数据,并对其进行了更新,但同时尚未完成事务,因此还没有进行事务提交,而与此同时,允许另一个事务也能够访问该数据。举个例子来说,事务A和事务B同时进行,事务A在整个执行阶段,会将某数据项的值从1开始,做一系列加法操作(比如说加1操作)直到变成10之后进行事务提交,此时,事务B能够看到这个数据项在事务A操作过程中的所有中间值(如1变成2、2变成3等),而对这一系列的中间值的读取就是未授权读取。
  2. 授权读取
    授权读取也被称为读已提交(Read Committed),它和未授权读取非常相近,唯一的区别就是授权读取只允许获取已经被提交的数据。同样以上面的例子来说,事务 A和事务同时进行,事务A进行与上述同样的操作,此时,事务B无法看到这个数据项在事务A操作过程中的所有中间值,只能看到最终的10。但仍然会有不可重复读的问题发生。
  3. 可重复读取
    可重复读取(Repeatable Read),简单地说,就是保证在事务处理过程中,多次读取同一个数据时,其值都和事务开始时刻是一致的。因此该事务级別禁止了不可重复读取和脏读,但是有可能出现幻影数据。所谓幻影数据,就是指在一次事务操作之内,在前后两个时间执行对同一个数据项的读取,可能出现不一致的结果。在上面的例子,可重复读取隔离级别能够保证事务B在第一次事务操作过程中,始终对数据项读取到 1,但是在下一次事务操作中,即使事务 B (注意,事务名字虽然相同,但是指的是另一次事务操作)采用同样的查询方式,就吋能会读取到10或20。
  4. 串行化
    串行化( Serializable)是最严格的事务隔离级別。它要求所有事务都被串行执行,即事务只能一个接一个地进行处理,不能并发执行。
    三种事务隔离性问题的解读:
  • 脏读:脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
  • 不可重复读:不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
  • 幻读:幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

@Transactional

Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编码式声明式的两种方式。编程式事务指的是通过编码方式实现事务;声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。声明式事务管理使业务代码逻辑不受污染, 因此在实际使用中声明式事务用的比较多。声明式事务有两种方式,一种是在配置文件(xml)中做相关的事务规则声明,另一种是基于@Transactional 注解的方式。
声明性事务的原理:
Spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入,这样就在代理中为我们把相关的事务处理掉了(开启正常提交事务,异常回滚事务)。真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。一个事务的基本属性包括了事务的隔离规则、传播规则、回滚规则、超时规则和是否只读;这些规则与@Transactional注解中的属性相对应。
打开@Transactional的注解源码可以发现该注解拥有以下属性:

public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";

    @AliasFor("value")
    String transactionManager() default "";

    Propagation propagation() default Propagation.REQUIRED;

    Isolation isolation() default Isolation.DEFAULT;

    int timeout() default -1;

    boolean readOnly() default false;

    Class<? extends Throwable>[] rollbackFor() default {};

    String[] rollbackForClassName() default {};

    Class<? extends Throwable>[] noRollbackFor() default {};

    String[] noRollbackForClassName() default {};
}
  • transactionManager和value互为别名,表示我们选用的事务代理器,包含以下选项:JDBC、JPA、Hibernate、JDO分布式事务;设定后Spring会将事务指定到现有的PlatformTransactionManager bean的引用,通知会使用该引用。
  • isolation()描述了事务的隔离规则,从低到高等级分别为0~3;
  • propagation()表示事务的传播规则,事务的传播是指事务的嵌套的时候它们的事务属性。常见的传播属性有如下几个:PROPAGATION_REQUIRED(spring 默认):嵌套事务B在被加载时检查是否已经在事务中了,如果已经在被嵌套事务A中则不再另起事务,否则起新事务,若被嵌套事务A发生异常则A和B都将回滚;PROPAGATION_REQUIRES_NEW:无论嵌套事务B是否处在事务中被加载时都将另起新事务,被嵌套事务A(如存在)会被挂起,若被嵌套事务A发生异常则B不会回滚;PROPAGATION_SUPPORTS:嵌套事务B是否被加载完全取决于被嵌套事务A是否被加载,若A没被加载,换言之B不是以嵌套事务的方式运行,则B不会被加载。
  • timeout() 描述了事务的超时规则.超过这个时间,发生回滚
  • readOnly() 描述了事务的只读规则,如果事务只对后端的数据库进行该操作,数据库可以利用事务的只读特性来进行一些特定的优化。通过将事务设置为只读,你就可以给数据库一个机会,让它应用它认为合适的优化措施。
  • 以下属性共同描述了事务的回滚规则;这些规则定义了哪些异常会导致事务回滚而哪些不会。默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚
    rollbackFor()导致事务回滚的异常类数组.
    rollbackForClassName() 导致事务回滚的异常类名字数组
    noRollbackFor 不会导致事务回滚的异常类数组
    noRollbackForClassName 不会导致事务回滚的异常类名字数组
    事务就是通过AOP实现的,事实上,Spring事务是AOP的最佳实现之一
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值