概述:由若干个数据库操作(CURD)组成的一个执行逻辑单位
事务内的所有操作要么全部成功,要么全部失败
不同的事务内的操作是互不影响的(如:一个方法并发10个开启了10个事务,10个事务的执行操作是一样的,且相互不干扰)
事务执行前后数据库的状态是一致的(符合数据库完整性约束)
数据库完整性:指的是数据库数据的正确性和有效性
正确性:通俗的说数据库的数据是符合书库语法和规约(如在插入数据时会判断主键是否唯一,这个判断是因为存在数据库主键唯一约束规约的存在;是否允许空;唯一约束…)
可靠性:数据库数据是对的(待补充)
事务提交后,对数据库的操作是永久的,且不能被回滚
读了其他事务未提交的数据(假数据)
在一个事务操作内操作某条数据,多次读取的数据结果不一样(一个事务操作内,其他事务被提交,数据被更改)(边读边写)
多个事务同时操作,读到数据不是自己开始写的数据(如:查询一个数据列表,读的时候有10条,写的时候发现有11条)(同时写和同时读)
脏读是读取了未提交的事务,不可重复读和幻读是读取了已经提交的事务
读未提交read-uncommitted、读已提交read-committed、可重复读repearable-read、串行化serializable
MySql的默认隔离级别是 可重复读repearable-read 、 SqlServer和Oracle为读已提交
查询隔离级别:
MySql8前: select @@tx_isolation;
MySQL8: select @@transaction_isolation
会话的事务隔离级别 SELECT @@SESSION.transaction_isolation,@@SESSION.transaction_read_only;
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 read-uncommitted | 是 | 是 | 是 |
读已提交 read-committed | 否 | 是 | 是 |
可重复读 repearable-read | 否 | 否 | 是 |
串行化 serializable | 否 | 否 | 否 |
Spring事务分类: 声明式事务(注解式@Transaction)、编程式事务(手动开启事务))
代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则自己新建事务,
代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则该方法在非事务的上下文中执行
代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则抛出异常
创建一个新的事务上下文,如果当前方法的调用者已经有了事务,则挂起调用者的事务,这两个事务不处于同一上下文,如果各自发生异常,各自回滚
该方法以非事务的状态执行,如果调用该方法的调用者有事务则先挂起调用者的事务
该方法以非事务的状态执行,如果调用者存在事务,则抛出异常
如果当前上下文中存在事务,则以嵌套事务执行该方法,也就说,这部分方法是外部方法的一部分,调用者回滚,则该方法回滚,但如果该方法自己发生异常,则自己回滚,不会影响外部事务,如果不存在事务,则与PROPAGATION_REQUIRED一样
引入Spring默认的事务配置对象
@Autowired
private PlatformTransactionManager platformTransactionManager;
@Autowired
private TransactionDefinition transactionDefinition;
//手动开启、提交和回滚事务
TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
//提交事务
platformTransactionManager.commit(transactionStatus);
//回滚事务
platformTransactionManager.rollback(transactionStatus);
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取;获取事务状态后,Spring根据传播行为来决定如何开启事务
TransactionStatus status =platformTransactionManager.getTransaction(def);
TransactionTemplate template = new TransactionTemplate(txManager);
template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
//重写execute方法实现事务管理
template.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
jdbcTemplate.update(INSERT_SQL, "饿死"); //字段sd为int型,所以插入肯定失败报异常,自动回滚,代表TransactionTemplate自动管理事务
}}
);
@Autowired
private TransactionTemplate transactionTemplate;
Boolean isSuccess = transactionTemplate.execute(new TransactionCallback() {
public Boolean doInTransaction(TransactionStatus status) {
Boolean result = true;
try {
// TODO
} catch (Exception e) {
status.setRollbackOnly();
result = false;
// TODO
}
return result;
}
});
回滚规则:执行方法中抛出了未检查异常或者调用了status.setRollbackOnly()方法,都会执行事务的回滚
提交规则:方法执行完毕则默认提交事务
TransactionCallback接口有一个子接口 TransactionCallbackWithoutResult,该接口中定义了一个 doInTransactionWithoutResult() 方法,TransactionCallbackWithoutResult 接口主要用于事务过程中不需要返回值的情况。当然,对于不需要返回值的情况,我们仍然可以使用 TransactionCallback 接口,并在方法中返回任意值即可.
注意:在使用了@Transaction注解的方法内不可使用transactionTemplate, 否则会导致异常:Transaction rolled back because it has been marked as rollback-only。
源码(DataSourceTransactionManagerAutoConfiguration.class、TransactionTemplate.class)
@Bean
@ConditionalOnMissingBean({PlatformTransactionManager.class})
public DataSourceTransactionManager transactionManager(DataSourceProperties properties){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource);
if (this.transactionManagerCustomizers != null){
this.transactionManagerCustomizers.customize(transactionManager);}return transactionManager;
}
备注:有兴趣可以了解一下DataSourceTransactionManager的写法和原理。
@Bean
@ConditionalOnMissingBeanpublic
TransactionTemplate transactionTemplate() {
return new TransactionTemplate(this.transactionManager);
}