事务:数据库中多个操作合并在一起形成的操作序列,事务特征(ACID)
作用:
Spring 事务一般加到业务层,对应着业务的操作,Spring 事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,Spring 是无法提供事务功能的,Spring 只提供统一事务管理接口
Spring 在事务开始时,根据当前环境中设置的隔离级别,调整数据库隔离级别,由此保持一致。程序是否支持事务首先取决于数据库 ,比如 MySQL ,如果是 Innodb 引擎,是支持事务的;如果 MySQL 使用 MyISAM 引擎,那从根上就是不支持事务的
保证原子性:
TransactionDefinition 接口中定义了五个表示隔离级别的常量:
MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)
分布式事务:允许多个独立的事务资源(transactional resources)参与到一个全局的事务中。事务资源通常是关系型数据库系统,但也可以是其他类型的资源,全局事务要求在其中的所有参与的事务要么都提交,要么都回滚,这对于事务原有的 ACID 要求又有了提高
在使用分布式事务时,InnoDB 存储引擎的事务隔离级别必须设置为 SERIALIZABLE
事务传播行为是为了解决业务层方法之间互相调用的事务问题,也就是方法嵌套:
当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。
例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行
//外层事务 Service A 的 aMethod 调用内层 Service B 的 bMethod
class A {@Transactional(propagation=propagation.xxx)public void aMethod {B b = new B();b.bMethod();}
}
class B {@Transactional(propagation=propagation.xxx)public void bMethod {}
}
支持当前事务的情况:
TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务则加入该事务;如果当前没有事务则创建一个新的事务
内外层是相同的事务,在 aMethod 或者在 bMethod 内的任何地方出现异常,事务都会被回滚
工作流程:
TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
不支持当前事务的情况:
TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起
TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起
TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常
其他情况:
TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务(两个事务没有关系)来运行
requied:必须的、supports:支持的、mandatory:强制的、nested:嵌套的
事务超时,指一个事务所允许执行的最长时间,如果超过该时间限制事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒,默认值为 -1
对于只有读取数据查询的事务,可以指定事务类型为 readonly,即只读事务;只读事务不涉及数据的修改,数据库会提供一些优化手段,适合用在有多条数据库查询操作的方法中
读操作为什么需要启用事务支持:
autocommit
模式,在该模式下,每一个发送到 MySQL 服务器的 SQL 语句都会在一个单独的事务中进行处理,执行结束后会自动提交事务,并开启一个新的事务@Transactional
注解,这个方法执行的所有 SQL 会被放在一个事务中,如果声明了只读事务的话,数据库就会去优化它的执行,并不会带来其他的收益。如果不加 @Transactional
,每条 SQL 会开启一个单独的事务,中间被其它事务修改了数据,比如在前条 SQL 查询之后,后条 SQL 查询之前,数据被其他用户改变,则这次整体的统计查询将会出现读数据不一致的状态
上一篇:关键词(三)