ACID
1、原子性(Atomicity):事务被作为一个整体执行,一个事务中的所有操作,要么都执行,要么都不执行
2、一致性(Consistency):确保数据库的状态从一个一致状态转到另一个一致状态
3、隔离性(Isolation):多个事务并发执行时,一个事务的执行不影响其它事务
4、持久性(Durability):当一个事务提交之后,被提交的事务应当永久保存在数据库中,不可被回滚
隔离级别
InnoDB默认的隔离级别是REPEATABLE READ
名称 | 描述 |
---|---|
read-uncommited | 读未提交 |
read-commited | 读提交(Oracle数据库默认的隔离级别) |
repeatable-read | 可重复读(MySQL数据库默认的隔离级别) |
serialized-read | 序列化读 |
安全问题
问题 | 描述 |
---|---|
脏读 | 一个事务读取到另一个事务还未提交的数据。大于等于 read-commited 可防止 |
不可重复读 | 一个事务内多次读取一行数据的相同内容,其结果不一致。大于等于 repeatable-read 可防止 |
幻读 | 一个事务内多次读取一张表中的相同内容,其结果不一致。serialized-read 可防止 |
1、读未提交可能产生脏读
-
脏读:一个事务读取到另一个事务还未提交的数据
-
解决:将事务的隔离级别提高到读已提交
2、读已提交可能产生不可重复读
- 不可重复读:一个事务内多次读取同一行数据的结果不一致
- 解决:将事务的隔离级别提高到可重复读
3、可重复读可能产生幻读
- 幻读:一个事务内多次读取同一张表数据的结果不一致
- 解决:将事务的隔离级别提高到序列化读
4、序列化读的事务隔离级别最高,不会产生问题,但效率也是最低的
传播行为
事务的传播行为一共有七种:
SUPPORTS:不存在外部事务,则不开启新事务;存在外部事务,则合并到外部事务中。(适合查询)
REQUIRED:不存在外部事务,则开启新事务;存在外部事务,则合并到外部事务中。 (默认值)(适合增删改)
MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与REQUIRED类似的操作。
Spring中如何配置事务
xml配置
准备工作:先配置好连接数据库的相关配置,然后在Spring的配置文件中再配置事务
1、创建事务管理器
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
2、配置事务详情
- 指定具体要添加事务的方法、隔离级别和传播行为等
<tx:advice id="myAdvice" transaction-manager="dataSourceTransactionManager">
<tx:attributes>
<!--具体要添加事务的方法-->
<tx:method name="transMoney" isolation="REPEATABLE_READ" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
3、AOP配置
- 配置切入点表达式等
<aop:config>
<aop:pointcut id="myPointcut" expression="execution(* com.robot.service.*.*(..))"/>
<aop:advisor advice-ref="myAdvice" pointcut-ref="myPointcut"/>
</aop:config>
由此三步,即可配置好Spring中的事务
注解配置
准备工作:先配置好连接数据库的相关配置
1、创建事务管理器
- 在Spring的配置文件applicationContext.xml中配置事务管理器
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
2、扫描注解、配置事务的注解驱动
<context:component-scan base-package="com.robot.service"/>
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
3、在需要开启事务的方法上使用注解
@Transactional
public void transMoney(String myCardNo, String targetCardNo, BigDecimal money) {
// 自己账户取钱
accountDao.take(myCardNo, money);
int i = 1 / 0; // 模拟异常
// 对方账户存钱
accountDao.save(targetCardNo, money);
}
使用注解的方式,配置文件中的<tx:advice… 和<aop:config…都可以省略,减少了很多配置,
而具体的细节配置等可以在注解中配置,例如:配置隔离级别、传播行为等
@Transactional(isolation=Isolation.READ_COMMITTED,propagation=Propagation.REQUIRED,readOnly=false,rollbackFor=Exception.class,timeout = -1)