事务
简介
事务是数据库操作的基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败。
事务是逻辑上的一组操作,要么都执行,要么都不执行。
事务最经典的例子莫过于转账了。
假如小明要给小红转账 1000 元,这个转账会涉及到两个关键操作就是:
- 将小明的余额减少 1000 元。
- 将小红的余额增加 1000 元。
万一在这两个操作之间突然出现错误比如银行系统崩溃或者网络故障,导致小明余额减少而小红的余额没有增加,这样就不对了。事务就是保证这两个关键操作要么都成功,要么都要失败。
ACID 四特性
- 原子性(Atomicity):事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
- 一致性(Consistency):执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
- 隔离性(Isolation):并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
- 持久性(Durability):一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
详细的可以去了解下这篇文章。
编程式事务管理
@Autowired private PlatformTransactionManager transactionManager; public void testTransaction() { TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); try { // .... 业务代码 transactionManager.commit(status); } catch (Exception e) { transactionManager.rollback(status); } }
声明式事务管理
- 基于注解
@Transactional(propagation = Propagation.REQUIRED) public void aMethod { B b = new B(); C c = new C(); b.bMethod(); c.cMethod(); }
@Transactional 的常用配置参数:
属性名 |
说明 |
propagation |
事务的传播行为,默认值为 REQUIRED,可选的值在上面介绍过 |
isolation |
事务的隔离级别,默认值采用 DEFAULT,可选的值在上面介绍过 |
timeout |
事务的超时时间,默认值为-1(不会超时)。如果超过该时间限制但事务还没有完成,则自动回滚事务。 |
readOnly |
指定事务是否为只读事务,默认值为 false。 |
rollbackFor |
用于指定能够触发事务回滚的异常类型,并且可以指定多个异常类型。 |
- 基于xml配置文件方式
<!--创建事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--注入数据源--> <property name="dataSource" ref="dataSource"></property> </bean> <!--开启事务注解--> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
事务属性
事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上。
事务属性包含了 5 个方面:
- 传播行为
- 隔离级别
- 回滚规则
- 是否只读
- 事务超时
事务传播行为
事务传播行为:在多事务方法直接进行调用,这个过程中事务是如何进行管理的。
事务方法:对数据库表数据进行变化的操作。(增删改)
7种事务传播行为
@Service @Transactional(propagation = Propagation.REQUIRED)
隔离级别
事务有特性成为隔离性,多事务操作之间不会相互影响。
不考虑隔离性会出现是三个读问题
- 脏读
- 不可重复读
- 虚读(幻读)
脏读(问题):一个未提交事务读取到另一个未提交事务的数据
不可重复读(现象):一个未提交事务读取到另一个提交事务修改数据
虚读(幻读):一个未提交事务读取到另一个提交事务添加数据
设置隔离级别,解决读问题。
详情可以看一下文章。
事务超时属性
事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。
timeout:超时时间
事务需要在一定时间进行提交,不提交就回滚,默认值为-1,即不超时
事务只读属性
对于只有读取数据查询的事务,可以指定事务类型为 readonly,即只读事务。
readOnly:是否只读
readOnly,默认FALSE,表示可以查询,修改,添加删除操作。
部分网上网友的解读:
- 如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持 SQL 执行期间的读一致性;
- 如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询 SQL 必须保证整体的读一致性,否则,在前条 SQL 查询之后,后条 SQL 查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持
事务的回滚规则
在默认设置下,事务只在出现运行时异常(runtime exception)时回滚,而在出现受检查异常(checked exception)时不回滚(这一行为和EJB中的回滚行为是一致的)。
不过,可以声明在出现特定受检查异常时像运行时异常一样回滚。同样,也可以声明一个事务在出现特定的异常时不回滚,即使特定的异常是运行时异常。
- rollBackFor 回滚:出现哪些异常设置哪些事务回滚
- norollBackFor 不回滚:出现异常哪些不回滚
@Transactional(rollbackFor= xxx.class)