一、事务四大特性
1、原子性 atomicity:事务不可分,提交便一次性提交
2、一致性 consistency:事务执行前后数据保持完整性,经典例子是银行转账前后双方的总额需保持不变,类似能量守恒
3、隔离性 isolation:不同事务执行之间需保持隔离,不相互影响
4、持久性 durability:事务结束造成的改变便持久到数据库
二、并发问题
1、脏读①:A读到B还未提交的事务,如果B回滚操作,此时A读到的便是无效的数据
2、丢失更新②:A和B同时修改同一条数据,A先修改,B后修改,最后B要回滚结果把A更新的给丢了(一类丢失);A和B同时修改同一条数据,A先修改,B后修改,最后B把A的修改给覆盖了(二类丢失)
3、不可重复读③:A事务的内读取数据,然后B事务此时修改了某一数据,A的同个事务再读一次发现数据已经变化(和“幻读”的差别,这个强调更新)
4、幻读④:A事务的内读取数据,此时B插入了一条新数据,A的同个事务再读一次数据就多了一条(和“不可重复”差别,这个强调插入、删除)
三、事务隔离级别 Isolation,指并发事务之间的隔离程度(后面的编号指在该级别下会出现的问题,对应上方并发问题的编号)
1、read_umcommited:①②③④
2、read_commited:②③④
3、repeatbale read:④
4、serializble:
四、事务传播行为 Propagation,指开始当前事务之前,一个事务上下文已经存在,此时选择的事务执行方式
1、REQUIRED(required):先选当前事务,如果没有就新建事务
2、SUPPORTS(supports):选当前事务,如果没有就不用事务
3、MANDATORY(mandatory):选当前事务,如果没有就抛异常
4、REQUIRED_NEW(required_new):直接新建事务,当前的事务挂起
5、NOT_SUPPORTED(not_supported):非事务执行,当前事务挂起
6、NEVER(never):非事务执行,如果当前有就抛异常
7、NESTED(nested):当前事务嵌套一个事务,如果没有就新建事务
五、Springboot增加事务处理
1、在项目启动类增加注解 @EnableTransactionManagement ,打开事务管理
2、指定事务管理器,springboot的事务管理器都继承于 PlatformTransactionManager,而且会自动注入,如果是引入了 spring-boot-starter-jdbc,则使用的是 DataSourceTransactionManager,如果是引入了 spring-boot-starter-data-jpa,则使用的是 JpaTransactionManager。当然我们也可以自己定义Bean,自己决定注入哪个,比如在启动类定义事务管理器的Bean,如下:
@Bean
public PlatformTransactionManager txManager(DataSource ds){
return new DataSourceTransactionManager(ds);
}
3、在需要增加事务处理的地方增加 @Transactional ,默认处理级别是 RuntimeException
@Transactional
public void insertData(){
String sql = "insert into product values ('128','sadd','saf')";
Integer result = jdbcTemplate.update(sql);
throw new RuntimeException("异常");
}
@Transactional(rollbackFor = Exception.class)
4、事务回滚失败的几种情况
@Transactional
public void insertData(){
//这样会回滚失效
try {
String sql = "insert into product values ('129','sadd','saf')";
Integer result = jdbcTemplate.update(sql);
throw new RuntimeException("异常");
} catch (Exception e) {
e.printStackTrace();
}
}
@Autowired
JdbcTemplate jdbcTemplate;
@Transactional(rollbackFor = Exception.class)
public void testInsert() throws Exception{
insert();
}
public void insert() throws Exception{
insertData();
}
public void insertData() throws Exception{
String sql = "insert into product values ('133','sadd','saf')";
Integer result = jdbcTemplate.update(sql);
throw new Exception("异常");
}