Transactional事务隔离级别和传播性

Transactional注解

隔离级别

定义一个事务受其他并发事务影响程度。事务并发引发的问题。

  • 脏读:一个事务读取到另一个事务修改但还未提交的数据
  • 不可重复读:一个事务读取数据之后,该数据被其他事务修改,此时第一个事务读取到的事务就是错误的(强调修改)
  • 幻读:一个事务读取了某些数据,没提交再读取时数据多了或者少了,类似幻觉(强调增删)
  • 丢失修改:两个事务都读取了数据,其中一个事务修改之后,另一个事务也做了修改,前者的修改丢失。、

我们这里先看看@Transaction注解

//可以放在 类上 或者 方法上。 
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {

	/**
	 * 区别于 transactionManager属性
	 * 查看 transactionManager
	 */
	@AliasFor("transactionManager")
	String value() default "";

	/**
	 * 选定特定的 事务管理器 SpringBoot中默认不用配置 可以是beanName或者特定的值
	 */
	@AliasFor("value")
	String transactionManager() default "";

	/**
	 * 设置传播级别
	 */
	Propagation propagation() default Propagation.REQUIRED;

	/**
	 * 设置事务隔离级别
	 */
	Isolation isolation() default Isolation.DEFAULT;

	/**
	 * 事务超时
	 */
	int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

	/**
	 * 事务只读 默认是可以修改的 如果设置为true只能执行查询相关
	 */
	boolean readOnly() default false;

	/**
	 * 指定错误回滚 当未抛出该类型的错误或者其子类的错误时 不会回滚 默认是任何错误(异常)都会回滚
	 */
	Class<? extends Throwable>[] rollbackFor() default {};

	/**
	* 略 
	*/
	String[] rollbackForClassName() default {};

	/**
	* 如果配置这个 如果抛出此异常将不会回滚
	*/
	Class<? extends Throwable>[] noRollbackFor() default {};

	/**
	* 略 
	*/
	String[] noRollbackForClassName() default {};

}

可以看到这上面我们主要关注 isolation(事务隔离级别)和propagation(事务传播级别)

五种隔离级别(RU、RC、RR、Serializable)

这里的隔离级别也映射了Mysql或Oracle的隔离级别。

我们先查看一下Isolation枚举类的源码

public enum Isolation {

	/**
	 * 使用默认的隔离级别
	 * 所有其他级别对应于JDBC隔离级别
	 * 具体隔离级别 查看 java.sql.Connection
	 * Mysql 默认 RR(REPEATABLE_READ)
	 * Oracle 默认 RC(READ_COMMITTED)
	 */
	DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),

	/**
	 * 未提交读 什么问题都不解决
	 * @see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED
	 */
	READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),

	/**
     * 提交读 解决脏读
	 * @see java.sql.Connection#TRANSACTION_READ_COMMITTED
	 */
	READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),

	/**
     * 可重复读 解决脏读和不可重复读 不解决幻读
	 */
	REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),

	/**
	 * 串行读 解决所有的事务隔离问题
	 */
	SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);


	private final int value;


	Isolation(int value) {
		this.value = value;
	}

	public int value() {
		return this.value;
	}

}
隔离级别脏读不可重复读幻读
READ_UNCOMMITTED×××
READ_COMMITTED××
REPEATABLE_READ×
SERIALIZABLE

事务传播行为

用来描述 一个被事务传播行为修饰的方法嵌套进另一个方法 时,事务如何传播。

在Spring的@Transaction中,有个重要的属性:Propagation,指的是事务方法之间发生嵌套调用时,事务的传播行为(当前调用的这个方法的事务,和当前的其他事务之间的关系)。

我们查看一下Propagation枚举类的源码

public enum Propagation {

	/**
	 * Support a current transaction, create a new one if none exists.
	 * Analogous to EJB transaction attribute of the same name.
	 * <p>This is the default setting of a transaction annotation.
	 * 外围有事务则加入形成同一个事务,外围无事务则新开启,内部事务之间相互独立
	 */
	REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

	/**
	 * Support a current transaction, execute non-transactionally if none exists.
	 * Analogous to EJB transaction attribute of the same name.
	 * <p>Note: For transaction managers with transaction synchronization,
	 * {@code SUPPORTS} is slightly different from no transaction at all,
	 * as it defines a transaction scope that synchronization will apply for.
	 * As a consequence, the same resources (JDBC Connection, Hibernate Session, etc)
	 * will be shared for the entire specified scope. Note that this depends on
	 * the actual synchronization configuration of the transaction manager.
	 * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
	 * 若外围没有事务则非事务执行,有事务则同 REQUIRED
	 */
	SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

	/**
	 * Support a current transaction, throw an exception if none exists.
	 * Analogous to EJB transaction attribute of the same name.
	 * 使用外围事务,若外围无事务则抛出异常
	 */
	MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

	/**
	 * Create a new transaction, and suspend the current transaction if one exists.
	 * Analogous to the EJB transaction attribute of the same name.
	 * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
	 * on all transaction managers. This in particular applies to
	 * {@link org.springframework.transaction.jta.JtaTransactionManager},
	 * which requires the {@code javax.transaction.TransactionManager} to be
	 * made available to it (which is server-specific in standard Java EE).
	 * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
	 * 外围有无事务都开启新事务,相互独立,且与外围事务相互独立开 如果当前有事务,就把当前的事务挂起
	 */
	REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

	/**
	 * Execute non-transactionally, suspend the current transaction if one exists.
	 * Analogous to EJB transaction attribute of the same name.
	 * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
	 * on all transaction managers. This in particular applies to
	 * {@link org.springframework.transaction.jta.JtaTransactionManager},
	 * which requires the {@code javax.transaction.TransactionManager} to be
	 * made available to it (which is server-specific in standard Java EE).
	 * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
	 * 非事务执行,若外围存在事务则挂起该事务
	 */
	NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

	/**
	 * Execute non-transactionally, throw an exception if a transaction exists.
	 * Analogous to EJB transaction attribute of the same name.
	 * 非事务执行,当外围有事务则抛出异常
	 */
	NEVER(TransactionDefinition.PROPAGATION_NEVER),

	/**
	 * Execute within a nested transaction if a current transaction exists,
	 * behave like {@code REQUIRED} otherwise. There is no analogous feature in EJB.
	 * <p>Note: Actual creation of a nested transaction will only work on specific
	 * transaction managers. Out of the box, this only applies to the JDBC
	 * DataSourceTransactionManager. Some JTA providers might support nested
	 * transactions as well.
	 * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
	 * 外围无事务,则同 REQUIRED 内部开启新事务相互独立。外围有事务,则内部事务是其子事务,主事务回滚则子事务全部回滚,子事务回滚不影响其他子事务和主事务
	 */
	NESTED(TransactionDefinition.PROPAGATION_NESTED);


	private final int value;


	Propagation(int value) {
		this.value = value;
	}

	public int value() {
		return this.value;
	}

}

总结

在我们的日常开发过程中,设计到数据安全相关的问题的时候切记要选择正确的事务隔离和事务传播,多测试,以免造成没必要的经济损失。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
@TransactionalSpring 框架中的一个注解,用于配置事务管理。事务传播(Transaction Propagation)定义了当一个方法被包含在一个事务中时,如果当前存在事务,应该采取何种策略。Spring 提供了多种事务传播行为: 1. `PROPAGATION_REQUIRED` (默认值): 如果当前没有事务Spring 将开始一个新的事务;如果有事务,则加入到现有的事务中。这是最常见的行为,表示方法必须在事务上下文中执行。 2. `PROPAGATION_SUPPORTS`: 如果当前存在事务,方法将在该事务中执行;如果没有事务,方法将像 `REQUIRED` 一样开始新的事务。这适用于那些不需要强制在事务中的方法。 3. `PROPAGATION_MANDATORY`: 必须在事务中执行,如果没有事务,会抛出异常。这对于数据库操作中的强制原子很有用。 4. `PROPAGATION_REQUIRES_NEW`: 在新的事务中执行,无论当前是否存在事务。这适用于希望独立于现有事务运行的方法。 5. `PROPAGATION_NESTED`: 创建嵌套事务,如果当前存在事务,则开始新事务;否则就像 `REQUIRED`。通常用于读写操作的隔离级别控制。 6. `PROPAGATION_NOT_SUPPORTED`: 方法不会在事务上下文中执行,即使当前存在事务。 7. `PROPAGATION_NEVER`: 禁止事务传播,无论当前是否有事务,都会作为非事务方法执行。 相关问题: 1. 何时会选择使用 `PROPAGATION_REQUIRED` 或 `PROPAGATION_REQUIRES_NEW`? 2. 如何通过代码设置事务传播行为? 3. `PROPAGATION_NESTED` 和其他传播行为的主要区别是什么?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值