1.什么是事务
我们在实际业务场景中,经常会遇到数据频繁修改读取的问题。在同一时刻,不同的业务逻辑对同一个表数据进行修改,
这种冲突很可能造成数据不可挽回的错乱,所以我们需要用事务来对数据进行管理。
并发事务导致的问题
(1)第一类丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖
(2)脏读:一个事务读取到另一个事务未提交的更新数据。
(3)幻读也叫虚读:一个事务执行两次查询,第二次结果集包含第一次中没有或某些行已经被删除的数据,造成两次结果不一致,只是另一个事务在这两次查询中间插入或删除了数据造成的。
(4)不可重复读:一个事务两次读取同一行的数据,结果得到不同状态的结果,中间正好另一个事务更新了该数据,两次结果相异,不可被信任。
2. 事务的五个隔离级别
DEFAULT : 数据库的默认事务隔离级别
READ_UNCOMMITTED : 读未提交 。 未解决任何并发问题
READ_COMMITTED : 读已提交。解决脏读,存在不可重复读与幻读。
REPEATABLE_READ : 可重复读。解决脏读,不可重复读,存在幻读。
SERIAIZABLE : 串行化。不纯在并发问题。
3.事务的传播行为
REQUIRED : 指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中;若当前没有事务就新建一个事务。
SUPPORTS : 指定方法支持事务,如果没有事务也可以执行。 适合查询操作。 如果有事务就就执行事务吗,没有事务也执行
MANDATORY : 必须有事务,没事务就抛出异常
REQUIRES_NEW : 总是新建个事务,若当前方法有事务,也新建一个事务,之前的事务挂起
NOT_SUPPORTED : 纯在事务也不执行事务,一般没啥用
NEVER : 有事务就抛异常 : 也没啥用
NESTED : 如果存在事务,就嵌套事务执行,没事务就新建
4. Spring 事务代理工厂
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="myDataSource"/> 指定数据库数据源
Spring 使用 事务注解
@Transactional
需要 开启事务注解驱动
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"> <property name="dataSource" ref="myDataSource"/> </bean>
<!-- 开启事务注解驱动 transaction-manager:指定事务管理器bean的id -->
<tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional(propagation=Propagation.SUPPORTS,readOnly=true)