数据库事务

数据库事务:

一、事务的四个特征(ACID):原子性、一致性、隔离性、持久性

1.隔离级别(isolation)

①未提交读
两个同时进行的事务,在a事务数据未提交时,b事务就能读取到a事务带来的数据上的变化,这种隔离级别会造成脏读

读写提交
两个同时进行的事务,b事务只能读取a事务提交后的数据,不能读取a事务提交前已变动的数据,但可以读取数据库原有数据。(比如数据库原有5,a事务向其中插入3,在a事务插入之后且提交之前,b事务只能读取原有的5,在提交之后读取的是8),我们可以看到括号中出现了这样的现象,由于我们无法控制b事务的读取点是在a事务提交前还是提交后,b事务的读取操作有可能出现两种结果(5或者8),这种现象我们称为:不可重复读

③可重复读

如果b事务在a事务提交前读的话,系统会禁止其读取,直到a事务提交后,系统才会允许b事务进行读取。这样就解决了b事务读取时会出现两种结果的问题。与此可能出现的问题:幻读。幻读不像上边两种问题那样针对单条数据(解决脏读、不可重复读问题的方法其实是在单条数据上加了锁),它是面向多条数据产生的问题,比如:在a事务开始后且执行sql前,b事务读取了数据的count()总条数,a事务结束后,b事务再次读取数据的count()总条数时,两次读取的结果不一样。

④序列化(串行化)

最严格的隔离级别,事务会按照顺序,一个一个的执行。它不会出现脏读、不可重复读、幻读问题。

spring采取的默认隔离级别是跟数据库相关的,如:mysql的默认隔离级别为可重复读;oracle的默认隔离级别为读写提交

二、传播行为(七种)

① REQUIRED(默认):支持使用当前事务,如果当前事务不存在,创建一个新事务

SUPPORTS:支持使用当前事务,如果当前事务不存在,则不使用事务

MANDATORY:中文翻译为强制,支持使用当前事务,如果当前事务不存在,则抛出Exception

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

NOT_SUPPORTED:无事务执行,如果当前事务存在,把当前事务挂起

⑥ NEVER:无事务执行,如果当前有事务则抛出Exception

⑦ NESTED:嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。如果当前事务不存在,则表现跟REQUIRED一样

三、事务失效场景

①spring中事务失效:@Transactional注解使用的是AOP,在使用动态代理的时候只能针对public方法进行代理;

Spring事务是依靠AOP实现的,在A类的被代理对象的方法中去调用B类代理对象的方法,而如果A类的被代理对象方法中,调用了自身的一个方法,这个方法只是单纯的一个方法而已,并没有经过@Transactional实现AOP,事务失效

②在整个事务的方法中使用try-catch,导致异常无法抛出,自然会导致事务失效

③rollbackFor属性设置错误/noRollbackFor属性设置错误:指定异常触发回滚,一旦设置错误,导致一些异常不能触发回滚,此时的声明式事务就失效了

④propagation属性设置错误:默认的事务传播属性是Propagation.REQUIRED,但是一旦配置了错误的传播属性,也是会导致事务失效,如下三种配置将会导致事务失效:Propagation.SUPPORTS、Propagation.NOT_SUPPORTED、Propagation.NEVER

 ⑤原始ssm项目中,重复扫描导致事务失效:

在原始的SSM项目中都配置了context:component-scan并且同时扫描了service层,此时事务将会失效。

按照Spring配置文件的加载顺序来说,会先加载Springmvc的配置文件,如果在加载Springmvc配置文件的时候把service也加载了,但是此时事务还没加载,将会导致事务无法成功生效。

解决方法:把扫描service层的配置设置在Spring配置文件或者其他配置文件中即可

 

posted @ 2020-07-17 01:03  尚进生  阅读(129)  评论(0编辑  收藏  举报