zoukankan      html  css  js  c++  java
  • Spring关于事物的面试题

    关于事物的面试题:
      事务是逻辑处理原子性的保证手段,通过使用事务控制,可以极大的避免出现逻辑处理失败导致的脏数据等问题。
    事务最重要的两个特性,是事务的传播级别和数据隔离级别。
    1、传播级别定义的是事务的控制范围,
    2、事务隔离级别定义的是事务在数据库读写方面的控制范围。

    一、事物的七种传播级别

    1) PROPAGATION_REQUIRED ,默认的spring事务传播级别,使用该级别的特点是,如果上下文中已经存在事务,
    那么就加入到事务中执行,如果当前上下文中不存在事务,则新建事务执行。所以这个级别通常能满足处理大多数的业务场景。

    2)PROPAGATION_SUPPORTS ,从字面意思就知道,supports,支持,该传播级别的特点是,如果上下文存在事务,
    则支持事务加入事务,如果没有事务,则使用非事务的方式执行。所以说,并非所有的包在transactionTemplate.execute中的
    代码都会有事务支持。这个通常是用来处理那些并非原子性的非核心业务逻辑操作。应用场景较少。

    3)PROPAGATION_MANDATORY , 该级别的事务要求上下文中必须要存在事务,否则就会抛出异常!配置该方式的传播级别是有效的控制
    上下文调用代码遗漏添加事务控制的保证手段。比如一段代码不能单独被调用执行,但是一旦被调用,就必须有事务包含的情况,
    就可以使用这个传播级别。

    4)PROPAGATION_REQUIRES_NEW ,从字面即可知道,new,每次都要一个新事务,该传播级别的特点是,每次都会新建一个事务,
    并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。

    这是一个很有用的传播级别,举一个应用场景:现在有一个发送100个红包的操作,在发送之前,要做一些系统的初始化、验证、数据记录操作,
    然后发送100封红包,然后再记录发送日志,发送日志要求100%的准确,如果日志不准确,那么整个父事务逻辑需要回滚。
    怎么处理整个业务需求呢?就是通过这个PROPAGATION_REQUIRES_NEW 级别的事务传播控制就可以完成。发送红包的子事务不会直接影响到
    父事务的提交和回滚。

    5)PROPAGATION_NOT_SUPPORTED ,这个也可以从字面得知,not supported ,不支持,当前级别的特点就是上下文中存在事务,
    则挂起事务,执行当前逻辑,结束后恢复上下文的事务。

    这个级别有什么好处?可以帮助你将事务极可能的缩小。我们知道一个事务越大,它存在的风险也就越多。所以在处理事务的过程中,
    要保证尽可能的缩小范围。比如一段代码,是每次逻辑操作都必须调用的,比如循环1000次的某个非核心业务逻辑操作。
    这样的代码如果包在事务中,势必造成事务太大,导致出现一些难以考虑周全的异常情况。所以这个事务这个级别的传播级别就派上用场了。
    用当前级别的事务模板抱起来就可以了。

    6)PROPAGATION_NEVER ,该事务更严格,上面一个事务传播级别只是不支持而已,有事务就挂起,而PROPAGATION_NEVER传播级别要求
    上下文中不能存在事务,一旦有事务,就抛出runtime异常,强制停止执行!这个级别上辈子跟事务有仇。

    7)PROPAGATION_NESTED ,字面也可知道,nested,嵌套级别事务。该传播级别特征是,如果上下文中存在事务,则嵌套事务执行,
    如果不存在事务,则新建事务。

    二、什么是嵌套事务?

    嵌套是子事务套在父事务中执行,子事务是父事务的一部分,在进入子事务之前,父事务建立一个回滚点,叫save point,然后执行子事务,
    这个子事务的执行也算是父事务的一部分,然后子事务执行结束,父事务继续执行。重点就在于那个save point。看几个问题就明了了:

    1)如果子事务回滚,会发生什么?
    父事务会回滚到进入子事务前建立的save point,然后尝试其他的事务或者其他的业务逻辑,父事务之前的操作不会受到影响,更不会自动回滚。

    2)如果父事务回滚,会发生什么?
    父事务回滚,子事务也会跟着回滚!为什么呢,因为父事务结束之前,子事务是不会提交的,我们说子事务是父事务的一部分,正是这个道理。

    3)事务的提交,是什么情况?
    是父事务先提交,然后子事务提交,还是子事务先提交,父事务再提交?答案是第二种情况,还是那句话,子事务是父事务的一部分,
    由父事务统一提交。


    三、数据隔离级别分为不同的四种

    1、Serializable :最严格的级别,事务串行执行,资源消耗最大;

    2、REPEATABLE_READ :保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,
    但是带来了更多的性能损失。

    3、READ_COMMITTED :大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。
    该级别适用于大多数系统。

    4、Read_Uncommitted :保证了读取过程中不会读取到非法数据。


    四、脏读、不可重复读、幻读

    1、脏读 : 所谓的脏读,其实就是读到了别的事务回滚前的脏数据。比如事务B执行过程中修改了数据X,在未提交前,事务A读取了X,
    而事务B却回滚了,这样事务A就形成了脏读。

    2、不可重复读 :不可重复读字面含义已经很明了了,比如事务A首先读取了一条数据,然后执行逻辑的时候,事务B将这条数据改变了,
    然后事务A再次读取的时候,发现数据不匹配了,就是所谓的不可重复读了。

    3、幻读 :小的时候数手指,第一次数十10个,第二次数是11个,怎么回事?产生幻觉了?
    幻读也是这样子,事务A首先根据条件索引得到10条数据,然后事务B改变了数据库一条数据,导致也符合事务A当时的搜索条件,
    这样事务A再次搜索发现有11条数据了,就产生了幻读。


    五、一个对照关系表:
    Dirty reads non-repeatable reads phantom reads
    Serializable 不会 不会 不会
    REPEATABLE READ 不会 不会 会
    READ COMMITTED 不会 会 会
    Read Uncommitted 会 会 会

    所以最安全的,是Serializable,但是伴随而来也是高昂的性能开销。
    另外,事务常用的两个属性:readonly和timeout
    一个是设置事务为只读以提升性能。
    另一个是设置事务的超时时间,一般用于防止大事务的发生。还是那句话,事务要尽可能的小!

    六、Spring配置声明式事务

    * 配置DataSource
    * 配置事务管理器
    * 事务的传播特性
    * 那些类那些方法使用事务

    1、Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,
    一般变化的只是代理机制这部分。

    2、DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问 时,DataSource
    实际为SessionFactory,TransactionManager的实现为 HibernateTransactionManager。

    根据代理机制的不同,Spring事务的配置又有几种不同的方式:

    第一种方式:每个Bean都有一个代理

    第二种方式:所有Bean共享一个代理基类

    第三种方式:使用拦截器

    第四种方式:使用tx标签配置的拦截器

    第五种方式:全注解
    作者:donleo123
    本文如对您有帮助,还请多推荐下此文,如有错误欢迎指正,相互学习,共同进步。
  • 相关阅读:
    falling object思路总结
    Real-Time Compressive Tracking 论文笔记
    xgboost python windows编译问题
    云服务三大部署模式-私有云、公有云、混合云谁才是云计算未来的主流
    NS3网络仿真(12): ICMPv4协议
    Android隐藏输入法键盘(hideSoftInputFromInputMethod没有效果)
    leetcode-Gas Station
    BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第10章节--SP2013中OAuth概览 总结
    hdu4737A Bit Fun 线段树
    EA生成实体类代码
  • 原文地址:https://www.cnblogs.com/donleo123/p/14068263.html
Copyright © 2011-2022 走看看