数据库事务面试题

目录

1. 什么是事务?

2.事务的四大特性(ACDI)

3. 事务并发带来的问题?

4. 事务的隔离级别?

5. 事务的传播机制?  

6. 事务什么场景下会失效?

7. 在Spring/SpringBoot中你是怎样使用事务的? 


1. 什么是事务?

数据库事务(DataBase Transaction),是指一些列操作的集合;

这些操作要么完全的执行,要么完全的不执行;或者要么全部执行成功,要么全部失败;

在Spring中,Spring将事务写为一个内置的AOP。

2.事务的四大特性(ACDI)

原子性(Atomicity):最小颗粒度,不可拆分。如银行转账,一方扣款乙方收款,不可拆成两部分,一方只扣另一方收不到是不行的;

一致性(Consistency):数据库的状态保持一致,当事务执行后,数据库的状态不符合预期,事务将会回滚到开始的状态,以保证数据库的一致性。例如银行转账事务,一方扣款了另一方没收到,结果就是数据库状态不符合预期,所以事务应该回滚,确保扣款操作给数据库造成的影响被撤销还原,从而保持数据库的一致性;

持久性(Durability):事务一旦提交,对数据的影响是永久的,不可撤销。再如银行转账,已转成功后,扣款方后悔不想给转账了,让银行将钱退回是不应该的,除非让收款方主动转过来,那这就是另一个事务了;

隔离性(Isolation):事务之间相互独立没有关系,没有影响。

3. 事务并发带来的问题?

并发:同时发生

脏读:一个事务读到了另一个事务还没提交的数据,也就是另一个事务未成功的情况;

虚读(幻读):在一个事务的操作中发现了未被操作的数据;例如在a事务对全部数据做了操作之后,此时b事务发生了新增(删除)操作,a事务提交之后就会发现由于b新增(删除)之后a还没来得及处理的数据,像是发生了幻觉,a说:嗯???我好像全部处理了呀?

不可重复度:再同一个事务中,读取了两次某个数据但是结果不一致,在两次读数据的时间差内,数据被动了手脚;如持存折人查询余额有1000,这时由于持卡人用借记卡取走100,再次用存折查询为900,数据不一致。

4. 事务的隔离级别?

为了解决上面三种问题而生;

隔离级别越高,并发下产生的问题越少,但同时付出的性能消耗也将越大;所以每一级别并不完全完美,具体问题具体分析;

(Oracle,SQL Server默认级别是READ_COMMITTED,读已提交)

READ_UNCOMMITTED,读未提交,能够读取到没有被提交的问题;最低级别,三个问题都不解决,很少使用;

READ_COMMITTED,读已提交,能够读取到已经提交的数据,自然能够防止脏读,但是无法限制虚读和不可重复读;

DEFAULT,MySQL默认级别,REPEATABLE_READ,可重复读;保证两次读到的数据一致(在两次查询之间不允许其他操作)-->上锁--行级锁(sql语句中使用for update),两次读完后在解锁;也解决了脏读;但是解决不了虚读;

SERIALIZABLE,可串行(xing)化的,最高级别;不管多少事务,挨个执行完一个事务的所有操作之后,再执行另一个事务-->锁表;三个问题都可解决。但是此级别并不常用,因为多线程应用被设置此级别后,那就完全成了单线程应用,失去了多线程编程的意义。

综上来看,虚读无法从技术层面上合适的解决,则从业务角度想办法:
    补偿措施,对新增的数据进行补偿操作;
    冗余措施,提前想到有可能会有新增的数据;
    允许这种问题发生。

5. 事务的传播机制?

研究事务该不该有,或者该有几个;是Spring对事务加入的保证手段。

PROPAGATION_REQUIERD,要求事务,若没有就新建;--默认

PROPAGATION_MANDATORY(强制的),强制要事务,若没有则抛出异常;

PROPAGATION_REQUIRES_NEW,新建事务,若当前存在事务,把当前事务挂起不用;

PROPAGATION_SUPPORTS,支持当前事务,若没有,就以非事务运行;

PROPAGATION_NOT_SUPPORTED,不支持事务,若当前存在事务,则挂起不用;

PROPAGATION_NEVER,不支持事务,若当前存在事务,则抛出异常;

PROPAGATION_NESTED,若当前存在事务,则嵌套在事务内运行;若不存在,则执行与*_REQUIRED(默认)类似的操作,没有就新建。

6. 事务什么场景下会失效?

(1)注解标在了非public修饰的方法上;

        事务--内置AOP--JDK动态代理--共同实现某个接口--接口中的方法一定是public修饰--非public方法不能被外界调用,AOP就不可实现,所以失效;

(2)注解属性传播机制propagation设置错误,设置为非事务运行;

(3)注解属性rollbackFor()(因为什么原因导致事务回滚)设置错误;
        Spring在默认情况下,当抛出了未检查unchecked异常(继承自RuntimeException 的异常)或者Error才回滚事务,其他异常(如IO异常)不会触发回滚,即事务失效;但却期望Sprng能够回滚事务,就需要指定rollbackFor属性。

(4)同一个类中方法嵌套调用,除了入口处的注解,其他方法上的注解就会失效,因为违反了事务不开拆分特性;

(5)异常被catch处理,而不对外抛出,就认为是没有异常发生,导致事务失效。

 7. 在Spring/SpringBoot中你是怎样使用事务的?    

(1)通过xml文件中配置事务管理器、事务传播机制(哪个方法是哪个机制)、事务与切点配置(针对哪个方法配置事务);

<!-- Spring 事务管理器 -->
<bean id="txManager" class="...事务管理器所在的类" >
  <property name="dataSource" ref="dataSource"/>
</bean>

<!-- 事务的传播机制(给哪个方法指定哪个机制)-->
<tx:advice id="txAdivce" transaction-manager="txManager">
  <tx:attributes>
    <tx:method name="save*" propagation="REQUIRED"/>  <!--save打头的方法,机制为:-->
    <tx:method name="update*" propagation="REQUIRED"/>
    <tx:method name="*" read-only="true"/>    <!--所有方法只读-->
  </tx:attributes>
</tx:advice>

<!--切点配置(给哪个类或者类中的哪个方法配置事务)-->
<aop:config>
  <aop:pointcut id="txService" expression="切点表达式"/>
  <!-- 事务使用内置的切面调用 -->
  <aop:advisor advice-ref="txAdivce" pointcut-ref="txService"/>
</aop:config>

(2)通过注解配置,@Transactional,用注解代替了xml中原先事务传播机制和切点(事务管理器需要有),注意需要加上事务的注解驱动配置;注解可标在类上,表示此类所有方法启用事务;也可标在某个方法上,表示只对某个方法启用事务。

<!-- 打开事务注解驱动 -->
<tx:annotation-driven transaction-manager="txManager"/>
  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值