一个事务一旦其中有一个操作出现错误,事物的操作将全部回滚。系统将事务中对数据库的所有的已完成的操作全部撤消,回滚到事务开始的状态。
一个事务中的所有操作作为一个单元,要么完全地执行,要么完全地不执行。
事务是为了确保数据的完整性和一致性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
Spring 事务管理分为编程式和声明式的两种方式。编程式事务指的是通过编码方式实现事务,声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。声明式事务管理使业务代码逻辑不受污染, 因此在实际使用中声明式事务用的比较多。
声明式事务有两种方式,一种是在配置文件(xml)中做相关的事务规则声明,另一种是基于 @Transactional 注解的方式。
我们常用基于 @Transactional 注解的方式管理事务。
参考 Spring Boot @Transactional注解事务不回滚不起作用无效
首先要看数据库本身对应的库、表所设置的是什么引擎。MyIsam不支持事务,如果需要支持事务,必须改为InnnoDB
MySQL两种存储引擎: MyISAM和InnoDB
数据库中的存储引擎其实是对使用了该引擎的表进行某种设置,数据库中的表设定了什么存储引擎,那么该表在数据存储方式、数据更新方式、数据查询性能以及是否支持索引等方面就会有不同的“效果”。
参 数 名 称 | 功 能 描 述 |
---|---|
readOnly | 该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。例如:@Transactional(readOnly=true) |
rollbackFor | rollbackFor 该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如:指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class}) |
rollbackForClassName | 该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。例如:指定单一异常类名称@Transactional(rollbackForClassName=”RuntimeException”)指定多个异常类名称:@Transactional(rollbackForClassName={“RuntimeException”,”Exception”}) |
noRollbackFor | 该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如:指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class}) |
noRollbackForClassName | 该属性用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。例如:指定单一异常类名称:@Transactional(noRollbackForClassName=”RuntimeException”)指定多个异常类名称:@Transactional(noRollbackForClassName={“RuntimeException”,”Exception”}) |
propagation | 该属性用于设置事务的传播行为。例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true) |
isolation | 该属性用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置 |
timeout | 该属性用于设置事务的超时秒数,默认值为-1表示永不超时 事物超时设置: @Transactional(timeout=30) //默认是30秒 |
例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
Propagation属性 |
含义 |
REQUIRED |
默认值 在有transaction状态下执行;如当前没有transaction,则创建新的transaction; |
SUPPORTS |
如当前有transaction,则在transaction状态下执行;如果当前没有transaction,在无transaction状态下执行; |
MANDATORY |
必须在有transaction状态下执行,如果当前没有transaction,则抛出异常IllegalTransactionStateException; |
REQUIRES_NEW |
创建新的transaction并执行;如果当前已有transaction,则将当前transaction挂起; |
NOT_SUPPORTED |
在无transaction状态下执行;如果当前已有transaction,则将当前transaction挂起; |
NEVER |
在无transaction状态下执行;如果当前已有transaction,则抛出异常IllegalTransactionStateException。 |
例如:@Transactional(isolation = Isolation.READ_COMMITTED)
隔离级别 | 含义 |
---|---|
DEFAULT | 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别. 另外四个与JDBC的隔离级别相对应; |
READ_UNCOMMITTED | 最低的隔离级别。事实上我们不应该称其为隔离级别,因为在事务完成前,其他事务可以看到该事务所修改的数据。而在其他事务提交前,该事务也可以看到其他事务所做的修改。可能导致脏,幻,不可重复读 |
READ_COMMITTED | 大多数数据库的默认级别。在事务完成前,其他事务无法看到该事务所修改的数据。遗憾的是,在该事务提交后,你就可以查看其他事务插入或更新的数据。这意味着在事务的不同点上,如果其他事务修改了数据,你就会看到不同的数据。可防止脏读,但幻读和不可重复读仍可以发生。 |
REPEATABLE_READ | 比ISOLATION_READ_COMMITTED更严格,该隔离级别确保如果在事务中查询了某个数据集,你至少还能再次查询到相同的数据集,即使其他事务修改了所查询的数据。然而如果其他事务插入了新数据,你就可以查询到该新插入的数据。可防止脏读,不可重复读,但幻读仍可能发生。 |
SERIALIZABLE | 完全服从ACID的隔离级别,确保不发生脏读、不可重复读和幻影读。这在所有隔离级别中也是最慢的,因为它通常是通过完全锁定当前事务所涉及的数据表来完成的。代价最大、可靠性最高的隔离级别,所有的事务都是按顺序一个接一个地执行。避免所有不安全读取。 |
脏读 : 一个事务读取到另一事务未提交的更新数据
不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同。后续读取可以读到另一事务已提交的更新数据. 相反, "可重复读"在同一事务中多次读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据。
幻读 : 一个事务读到另一个事务已提交的insert数据
参考 MySQL事务 transaction
参考:
Spring Boot 中使用 @Transactional 注解配置事务管理
SpringBoot事务注解@Transactional
spring事物的七种事物传播属性行为及五种隔离级别
事物注解方式: @Transactional
Spring事务管理只对出现运行期异常进行回滚