004Spring事务002事务简介

1 了解事务

1.1 什么是事务

事务是一组逻辑处理单位,可以是执行一条SQL语句,也可以是执行几个SQL语句。

事务用来保证数据由一种存储情况变为另一种情况,组成事务的各个单元要么都执行成功,要么都执行失败。

1.2 事务的特性(ACID)

原子性(Atomicity):指事务包含的所有操作要么全部成功提交,要么全部失败回滚。

一致性(Consistency):指事务必须使数据库从一个一致性状态变换到另一个一致性状态。

隔离性(Isolation):指当多个用户并发访问数据库并且操作同一张表的时候,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

持久性(Durability):指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,哪怕是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

1.3 多事务并发操作产生的问题

对数据库事务的操作其实可以分为两类:一种是读取事务(Select),另一种是修改事务(Insert、Update、Delete)。

单个事务的情况下,事务操作不会产生并发问题,但是如果多个事务在同一时刻操作同一数据可能会影响最终期望的结果,产生并发问题。

主要的问题有四种:

1)更新丢失:更新时更新。两个更新事务同时更新一个数据,就会导致一个事务的更新操作丢失。

2)脏读:更新时读取。一个更新事务更新一条数据时,另一个读取事务读取了还没提交的数据,这时如果更新事务进行回滚,就会导致读到脏数据。

3)不可重复读:读取时更新。一个读取事务多次读取一条数据时,另一个更新事务修改并提交了这条数据,就会导致在更新事务提交的前后读取到了不同的数据。

4)幻读:读取时插入或删除。一个读取事务读取时,另一个插入事务插入了一条数据,或者另一个删除任务删除了一条数据,这样就可能多读或者少读出一条数据,出现幻读。

1.4 事务的隔离级别

1.4.1 是什么

因为多事务的并发问题的严重程度和解决问题产生的系统开销不同,为了解决不同程度的问题,SQL标准定义了隔离级别,每个级别都有各自的具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

事务传播属性可以在Transactional注解的isolation属性中定义。

1.4.2 事务的四种隔离级别

1)Read Uncommitted(读未提交)

最低的隔离级别,所有事务都可以看到其他未提交事务的执行结果。可避免更新丢失的发生。

2)Read Committed(读已提交)

大多数数据库系统的默认隔离级别,但不是MySQL默认的,一个事务只能看见已提交事务所做的改变。可避免更新丢失、脏读的发生。

3)Repeatable Read(可重复读)

MySQL的默认事务隔离级别,确保同一事务的多个实例在并发读取数据时,会看到同样的数据。可避免更新丢失、脏读、不可重复读的发生。

4)Serializable(串行化)

最高的隔离级别,通过强制事务排序解决多事务的并发问题。简言之,它是在每个读的数据行上加上共享锁,但这么做可能导致大量的超时现象和锁竞争。可避免更新丢失、脏读、不可重复读、幻读的发生。

1.4.3 总结

以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别越高,执行效率就越低。

像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。

MySQL的默认事务隔离级别是Repeatable Read级别,相比较其他存储引擎,InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了幻读的问题。

1.5 事务的传播行为

1.5.1 是什么

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

事务的传播行为可以由传播属性指定,事务传播属性可以在Transactional注解的propagation属性中定义,Spring定义了7种类传播行为。

1.5.2 事务的七个传播行为

1)REQUIRED

默认传播行为。

如果在其他事务方法里调用当前事务方法,当前方法就在其他方法的事务中执行。

如果没有事务方法调用,当前方法就开启一个新的事务执行。

2)REQUIRES_NEW

如果在其他事务方法里调用当前事务方法,其他方法的事务将会被挂起,当前方法开启一个新的事务执行,当前方法执行完成后再继续执行其他方法。

如果没有事务方法调用,当前方法就开启一个新的事务执行。

3)SUPPORTS

如果在其他事务方法里调用当前事务方法,当前方法就在其他方法的事务中执行。

如果没有事务方法调用,当前方法就不在事务中执行。

但是对于事务同步的事务管理器,SUPPORTS与不使用事务有少许不同。

4)NOT_SUPPORTED

如果在其他事务方法里调用当前事务方法,其他方法的事务将会被挂起,当前方法不在事务中执行,当前方法执行完成后再继续执行其他方法。

如果没有事务方法调用,当前方法就不在事务中执行。

5)MANDATORY

如果在其他事务方法里调用当前事务方法,当前方法就在其他方法的事务中执行。

如果没有事务方法调用,当前方法就抛出一个异常。

6)NEVER

如果在其他事务方法里调用当前事务方法,当前方法就抛出一个异常。

如果没有事务方法调用,当前方法就不在事务中执行。

7)NESTED

如果在其他事务方法里调用当前事务方法,当前方法就在其他方法的事务的嵌套中执行。

如果没有事务方法调用,当前方法就开启一个新的事务执行。

2 事务管理

2.1 编程式事务管理

2.1.1 说明

在编程式管理事务时,必须在每个事务操作中包含额外的事务管理代码,通过将事务管理代码嵌入到业务方法中来控制事务的提交和回滚。

2.1.2 步骤

获取数据库连接Connection对象。

取消事务的自动提交。

执行操作。

正常完成操作时手动提交事务。

执行失败时回滚事务。

关闭相关资源。

2.1.3 评价

使用原生的事务管理是所有事务管理方式的基石,同时也是最典型的编程式事务管理。

相对于核心业务而言,事务管理的代码显然属于非核心业务,会造成较大程度的代码冗余。

2.2 声明式事务管理

2.2.1 说明

大多数情况下比编程式事务管理更好用,它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。

事务管理作为一种横切关注点,可以通过AOP方法模块化,Spring通过SpringAOP框架支持声明式事务管理。

2.2.2 分类

基于注解的方式,经常使用,方便。

基于XML的方式。

3 导包

3.1 IOC容器需要的包

1 commons-logging-1.1.1.jar
2 spring-beans-4.0.0.RELEASE.jar
3 spring-context-4.0.0.RELEASE.jar
4 spring-core-4.0.0.RELEASE.jar
5 spring-expression-4.0.0.RELEASE.jar

3.2 AOP需要的包

1 spring-aop-4.0.0.RELEASE.jar
2 spring-aspects-4.0.0.RELEASE.jar

3.3 AspectJ动态代理

1 com.springsource.net.sf.cglib-2.2.0.jar
2 com.springsource.org.aopalliance-1.0.0.jar
3 com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

3.4 JdbcTemplate需要的包

1 spring-jdbc-4.0.0.RELEASE.jar
2 spring-orm-4.0.0.RELEASE.jar
3 spring-tx-4.0.0.RELEASE.jar

3.5 数据库驱动和数据源需要的包

1 c3p0-0.9.1.2.jar
2 mysql-connector-java-5.1.7-bin.jar

 

posted @ 2022-01-24 23:36  执笔未来  阅读(34)  评论(0编辑  收藏  举报