事务重点内容

1. 含义

        一组要么同时成功提交,要么同时失败回滚的sql语句,是数据库操作的一个执行单元。

2. 特性-ACID

        1)原子性(Atomicity)

                强调事务中的多个操作是一个整体:事务内所有操作是一个整体、最小执行单元,要么全部成功,要么全部失败。

        2)一致性(Consistency)

                强调事务中不会保存不一致的状态:从一个一致性状态转到另一个一致性状态,有一个失败,全部回滚。

        3)隔离性(Isolation)

                强调数据库事务中事务之间互相不可见:一个事务所做的修改在提交之前,其余的事务是不可见的,看不到事务的中间状态。

        4)持久性(Durability)

                强调数据库能永久保存数据库,一旦提交就不可撤销:事务提交,所有的修改都会永久保存到数据库。

3. 事务的并发问题

        1)脏读

                事务A读取了事务B尚未提交的数据。如果此时事务B由于失败导致数据回滚,那么事务A读取的数据就是脏数据。

                

        2)不可重复读(前后多次读取,数据内容不一致)

                事务A读取了事务B提交的数据。事务A查询时,事务B查询并修改了同一条数据并提交,事务A再次读取到事务B修改后的数据,发现两次读取数据不一致,系统读取不到重复的数据,成为不可重复读。

                

        3)幻读(前后多次读取,数据总量不一致)

事务A读取了事务B新增或删除的数据,导致总数量不一致。事务A查询时,事务B新增了数据并提交,事务A再次查询时发现数据总量多了几条,就像产生了幻觉。

                

        4)小总结

                脏读:读取了另一事务未提交的数据。

                不可重复读:读取了另一事务提交了的更改数据,针对update。

                幻读:读取了另一事务提交了的新增或删除数据,针对insert或delete。

4. 事务的隔离级别

        数据库事务的隔离级别有4个,由低到高分别是Read uncommitted 、Read committed 、Repeatable read 、Serializable,级别越高,数据越安全,但性能越低。

        分别可以解决脏读、不可重复读、幻读的问题。

        

        注意:Mysql中默认的隔离级别是:Repeatable read(可重复读)

5. 事务的传播行为

        REQUIRED :如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。

        SUPPORTS :如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

        MANDATORY :如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。

        REQUIRES_NEW :创建一个新的事务,如果当前存在事务,则把当前事务挂起。

        NOT_SUPPORTED :以非事务方式运行,如果当前存在事务,则把当前事务挂起。

        NEVER :以非事务方式运行,如果当前存在事务,则抛出异常。

        NESTED :如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 REQUIRED。

6. 事务的实现

        @Transactional注解,既可以添加在方法上又可以添加在类上,当注解添加在类级别上,表示该类所有的公共方法都配置了相同的事务属性信息,

如果类级别和方法级别都配置了@Transactional,应用程序会优先以方法级别的事务属性来管理事务,换言之,方法级别的事务属性会覆盖类级别的事务属性。

        建议:在业务层抛出异常,控制层统一处理。

7. 事务不生效

        1)访问权限问题

                java的访问权限主要有四种:private、default、protected、public,从左往右,权限依次变大;spring要求被代理的方法必须是public,其余权限spring不提供事务。

        2)方法用final、static修饰

                spring事务底层使用aop实现,jdk或cglib动态代理,如果使用final或static修饰了方法,在代理类里无法重写,无法实现事务。

        3)方法内部调用

                同一个类中有事务A的方法A调用了有事务B的方法B,相当于直接使用this调用方法B,所以事务B不生效

        解决方法

                a. 新加一个service

                        

                b. 在该service注入自己

                        

                c. 通过AopContent类

                        

        4)未被spring管理

使用spring的前提是,对象要被spring管理,如果service上不加@service注解,该类不由spring管理,事务自然不生效。

        5)表不支持事务

        6)多线程调用

        7)未开启事务

8. 事务不回滚

        1)错误的传播行为

                @Transactional(propagation = Propagation.NEVER),这种传播行为不支持事务,有事务会抛异常

        2)自己吞了异常-try...catch

                主动捕捉了异常并处理,导致框架无法感知异常,无法回滚。

        3)手动抛了别的异常

                默认RuntimeException(运行时异常)和error(错误)回滚,Eexception(非运行时异常)就不回滚。

        4)嵌套事务回滚(多了)

                

                实现只回归内部,不回滚外部,在内部手动捕捉异常-try...catch,并不继续往外抛。

                        

  • 57
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值