一、事务与数据库的隔离级别

1、事务的ACID属性

A(Atomicity):原子性,事务要么都成功,要么都失败,是一个整体

C(Consistency):一致性,事务前后数据保持一致,如张三去银行取钱,取了500,则张三到手500,银行扣除500,总数不变

I(Isolation):隔离性,多事务之间互相隔离,不受影响

D(Durability):持久性,事务一旦成功,其改变是永久性的。

2、mysql的隔离级别

隔离级别 脏读 不可重复读 幻读
未提交读
提交读
可重复读(默认级别)
串行化

脏读:读到了无用的数据,事务A增加了一条数据未提交,事务B读到了这条数据,最后事务A事务回滚,事务B则读到了脏数据

不可重复读:同一事务两次读,读到的数据不一致,另一事务对数据进行了修改

幻读:同一事务两次读,后一次读到的数据多了,另一事务插入了一条数据。

3、Oracle的隔离级别

支持两种隔离级别:读已提交(默认隔离级别)、串行化

二、spring的事务

1、spring事务的本质是数据库对事务的支持

2、单纯的jdbc想要想要用到事务,可以用以下步骤:

//1、获取连接
Connection con =DrivenManager.getConnection();
//2开启事务
con.setAutoConmmit(false);
//3执行CRUD

//4提交事务/回滚事务
con.commit()/con.rollback();
//5关闭连接
con.close();

而使用用spring @Trancational事务注解,spring会自动实现步骤2、4,那spring是如何字段实现2、4的呢?答案是:在spring启动时,spring通过配置文件或者注解生成相应的springbean,这个时候会查看拥有相关注解的类和方法,并且为这些类及方法生成相应的代理,并根据@Trancational中的参数,进行相关配置的注入,这样就通过代理的手段帮们实现了2、4步骤

真正的数据库底层的事务提交及回滚是通过binlog、redolog实现的

3、spring的隔离级别,与mysql的一致,多了一个默认级别

//默认隔离级别,取数据库的默认隔离级别
Isolation.DEFAULT
//读未提交
Isolation.READ_UNCOMMITTED
//读已提交
Isolation.READ_COMMITTED
//可重复读
Isolation.REPEATABLE_READ
//串行化(能解决脏读、不可重复读、幻读问题,但是效率低)
Isolation.SERIALIZABLE

4、spring的传播机制

支持当前事务 PROPAGATION_REQUIRED 如果当前没有事务,则新建,如果有,则加入
支持当前事务 PROPAGATION_SUPPORTS 支持当前事务,没有事务则不用事务
支持当前事务 PROPAGATION_MANDATORY 使用当前事务,没有则抛异常
不支持当前事务 PROPAGATION_REQUIRES_NEW 新建事务,若当前存在事务,则挂起当前事务
不支持当前事务 PROPAGATION_NOT_SUPPORTED 非事务,挂起当前事务
不支持当前事务 PROPAGATION_NEVER 非事务,当前存在事务则抛异常
内嵌事务 PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

5、事务对runtimeException(比如空指针、1/0 异常)会回滚,而Exception异常(如文件读写、网络问题)无法回滚,若需要Exception异常也回滚的话需要添加rollback=Exception.class

03-28 04:29