首页 > 其他分享 >Spring学习笔记_33——事务隔离级别和事务传播

Spring学习笔记_33——事务隔离级别和事务传播

时间:2024-11-12 13:17:29浏览次数:3  
标签:事务 transaction 隔离 33 Spring 传播 当前 级别

事务隔离级别和事务传播机制

事务隔离级别

事务隔离级别是数据库管理系统在处理多个事务时,用来隔离并发事务以防止数据不一致性的机制。不同的隔离级别提供了不同的保护级别,以防止脏读、不可重复读和幻读等并发问题。以下是SQL标准中定义的四种隔离级别,以及一个额外的ISOLATION_DEFAULT级别

1. ISOLATION_DEFAULT隔离级别
  • 定义:这是PlatformTransactionManager默认的隔离级别,它使用数据库默认的事务隔离级别。
  • 特点:不同的数据库系统可能有不同的默认隔离级别。例如,Oracle数据库的默认隔离级别是READ_COMMITTED,而MySQL数据库的默认隔离级别是REPEATABLE_READ。
2. ISOLATION_READ_UNCOMMITTED隔离级别(读未提交)
  • 定义:这是事务最低的隔离级别,允许一个事务读取另一个事务未提交的数据。
  • 特点
    • 会产生脏读、不可重复读和幻像读。
    • 由于可以读取未提交的数据,这种隔离级别可能会导致数据不一致。
    • 很少使用,因为它提供了最低的数据一致性保障。
3. ISOLATION_READ_COMMITTED隔离级别(读已提交)
  • 定义:保证一个事务修改的数据提交后才能被另一个事务读取。
  • 特点
    • 可以避免脏读,因为只能读取已提交的数据。
    • 可能会出现不可重复读和幻像读。例如,在一个事务中读取了某条记录后,另一个事务对该记录进行了修改并提交,那么再次读取该记录时,会得到不同的结果。
    • 是大多数情况下的推荐值,因为它提供了较好的数据一致性和并发性能平衡。
4. ISOLATION_REPEATABLE_READ隔离级别(可重复读)
  • 定义:这种事务隔离级别可以防止脏读和不可重复读。
  • 特点
    • 除了保证一个事务不能读取另一个事务未提交的数据外,还保证了在同一个事务中多次读取同一数据时,能够得到相同的结果。
    • 可能会出现幻像读。例如,在一个事务中读取了满足某条件的所有记录后,另一个事务插入了新的满足该条件的记录并提交,那么再次读取时会得到更多的记录。
    • 提供了比READ_COMMITTED更高的数据一致性保障。
5. ISOLATION_SERIALIZABLE隔离级别(可串行化)
  • 定义:这是花费最高代价但最可靠的事务隔离级别,事务被处理为顺序执行。
  • 特点
    • 除了防止脏读、不可重复读外,还避免了幻像读。
    • 通过将事务完全隔离,确保每个事务在执行时不会受到其他事务的干扰。
    • 会严重影响程序的性能,因为事务需要按顺序执行,无法并发处理。
    • 通常情况下不会用到该级别,除非对数据一致性有极高的要求

事务传播机制

枚举类Propagation结合与@Transactional注解使用,枚举里面定义的事务传播行为类型与TransactionDefinition接口中定义的事务传播类型相对应,在使用@Transactional注解时,使用的是Propagation枚举类型中的事务传播类型,并不是直接使用的TransactionDefinition接口中定义的事务传播类型。

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
	 */
	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 jakarta.transaction.TransactionManager} to be
	 * made available to it (which is server-specific in standard Jakarta 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 jakarta.transaction.TransactionManager} to be
	 * made available to it (which is server-specific in standard Jakarta 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
	 */
	NESTED(TransactionDefinition.PROPAGATION_NESTED);


	private final int value;


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

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

}
1. REQUIRED
  • 这是最常见的传播级别。如果当前存在事务,则加入该事务;如果当前没有事务,就新建一个事务。
  • 适用场景:这是最常用的事务传播行为,适用于大多数需要事务管理的场景。
  • 注意:外部不存在事务时,开启新的事物;外部存在事务时,加入到外部事物中,并且如果调用端发生异常,则调用端和被调用端的事物都将会回滚。在这种事务传播类型下,当前操作必须在一个事务中执行。
2. REQUIRES_NEW
  • 总是创建一个新的事务,如果当前存在事务,就把当前事务挂起。
  • 适用场景:当需要确保操作在一个全新的事务中执行,不受现有事务的影响时使用。例如,在记录日志或审计信息时,可能希望这些操作独立于主业务逻辑的事务之外。
  • 注意:新创建的事物和被挂起的事物没有任何关系,他们是两个不相干的独立的事物。外部事物失败回滚,不会回滚内部事务的执行结果。内部事务失败抛出异常,被外部事物捕获到时,外部事物可以不处理内部事务的回滚操作。
3. SUPPORTS
  • 如果当前存在事务,就加入该事务;如果当前没有事务,就以非事务方式执行。
  • 适用场景:那些不严格要求事务的场景,适用于读取数据等对数据一致性要求不高的场景。
  • 注意:外部不存在事务时,不会开启新的事务;外部存在事务时,加入到外部事务中。
4. MANDATORY
  • 如果当前存在事务,则加入该事务;如果当前没有事务,就抛出异常。
  • 适用场景:当方法必须运行在事务上下文中时使用,如果不在事务中调用会抛出异常。
  • 注意:这种事务传播类型具备强制性,当前操作必须存在事务,如果当前操作不存在事务,则抛出异常
5. NOT_SUPPORTED
  • 总是非事务地执行,如果当前存在事务,就把当前事务挂起。
  • 适用场景:当执行的操作不需要事务支持,或者执行非事务操作比在事务中执行更高效时使用。
  • 注意:如果当前操作存在事务,则把事务挂起,以非事物的方式运行。
6. NEVER
  • 总是非事务地执行,如果当前存在事务,则抛出异常。
  • 适用场景:那些绝对不能在事务中执行的操作。
  • 注意:
    • NEVER事务传播类型和NOT_SUPPORTED事务传播类型的区别是:如果当前存在事务,则NEVER事务传播类型会抛出异常,而NOT_SUPPORTED事务传播类型会把当前事务挂起,以非事务的方式运行。
    • NEVER事务传播类型与MANDATORY事务船舶类型的区别是:NEVER事务传播类型表示如果当前操作存在事务,则抛出异常;而MANDATORY事务传播类型表示如果当前操作不存在事务,则抛出异常。
7. NESTED
  • 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,行为与REQUIRED相同。
  • 适用场景:适用于需要在现有事务基础上添加子事务的情况,子事务可以独立提交或回滚而不影响父事务。

常用的事务传播类型

  • REQUIRED:这是默认的事务传播级别,适用于大多数需要事务管理的场景。
  • REQUIRES_NEW:适用于需要创建一个与当前事务完全隔离的新事务的场景,比如在当前事务中需要执行一些完全独立的数据库操作。
  • SUPPORTS:适用于那些不严格要求事务的环境,如果存在事务就使用,不存在则不使用。
  • NOT_SUPPORTED:适用于那些不应该在事务中执行的操作,比如读取配置信息等。

标签:事务,transaction,隔离,33,Spring,传播,当前,级别
From: https://blog.csdn.net/LuckyLay/article/details/143711775

相关文章