事务
1、什么是事务?
通常的观念认为,事务仅与数据库相关。
事务是一组原子操作单位,从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令。更简单的说就是:要么执行成功,要么撤销不执行。
既然事务的概念从数据库而来,那么Java事务是什么?之间有什么联系?
实际上,一个Java应用系统,如果要操作数据库,则通过JDBC来实现的。增加、修改、删除都是通过相应方法间接实现的,事务的控制也相应的转移到Java程序代码中。因此数据库操作的事务习惯上就称为Java事务。
2、为什么需要Java事务
事务是为解决数据安全操作提出的,事务控制实际上就是控制数据安全访问。
3、Java事务的类型
- JDBC事务
- JTA(Java Transaction API) 事务
-
4、三种Java事务的差异
JDBC事务控制的局限性在一个数据库连接内,但其使用简单
- JTA事务的功能强大,事务可以跨越多个数据库或多个DAO,使用也比较复杂
容器事务,主要指的是J2EE应用服务器提供的事务管理,局限于EJB应用使用
5、事务(Transaction)的四个属性(ACID)
原子性(Atomic) 对数据的修改要么全部执行,要么全部不执行
- 一致性(Consistent)在事务执行前后,数据状态保持一致性
- 隔离性(Isolation)一个事务的处理不能影响另一个事务的处理
持续性(Durable)事务处理结束,其效果在数据库中持久化。
6、事务并发处理可能引起的问题
脏读(dirty read) :一个事务读取了另一个事务尚未提交的数据
- 不可重复读(non-repeatable read): 一个事务的操作导致另一个事务前后两次读取到不同的数据
- 幻读(phanton read): 一个事务的操作导致另一个事务前后两次查询的结果数据量不同
举例:
- 事务A、B并发执行时,当A事务update后,B事务select读取到A尚未提交的数据,此时A事务rollback,则B读到的数据是无效的”脏”数据。
- 当B事务select读取数据后,A事务update操作更改B事务select到的数据,此时B事务再次读去该数据,发现前后两次的数据不一样。
- 当B事务select读取数据后,A事务insert或delete了一条满足A事务的select条件的记录,此时B事务再次select,发现查询到前次不存在的记录(“幻影”),或者前次的某个记录不见了。
以上内容摘抄自文章Java中事务总结详解(精华)
SpringBoot事务隔离等级和传播行为
1、开启事务管理
@SpringBootApplication
@EnableTransactionManagement //显示开启事物管理,springboot默认已经开启事物管理,可不用显示的注解
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2、配置事务
在需要添加事务的类或方法上使用@Transactional(import org.springframework.transaction.annotation.Transactional)
3、isolation 隔离级别(SpringBoot默认值为Isolation.DEFAULT)
- DEFAULT :默认值,表示使用底层数据库的默认隔离级别。大部分数据库为READ_COMMITTED(MySql默认隔离级别为REPEATABLE)
- READ_UNCOMMITTED :该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
- READ_COMMITTED :该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
- REPEATABLE_READ** **:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。
- SERIALIZABLE :所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
通过使用 isolation 属性设置,例如:@Transactional(isolation = Isolation.DEFAULT)
4、事务传播行为propagation(springboot默认值为Propagation.REQUIRED)
REQUIRED :如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
- SUPPORTS :如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
- MANDATORY :如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
- REQUIRES_NEW :创建一个新的事务,如果当前存在事务,则把当前事务挂起。
- NOT_SUPPORTED :以非事务方式运行,如果当前存在事务,则把当前事务挂起。
- NEVER :以非事务方式运行,如果当前存在事务,则抛出异常。
- NESTED :如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 REQUIRED 。
- 指定方法:通过使用 propagation 属性设置,例如:@Transactional(propagation = Propagation.REQUIRED)
以上内容摘抄自文章SpringBoot事务隔离等级和传播行为