Transaction Propagation
本节描述了 Spring 中事务传播的一些语义。请注意,本节并不是对事务传播的正确介绍。相反,它详细介绍了 Spring 中有关事务传播的一些语义。
This section describes some semantics of transaction propagation in Spring. Note that this section is not a proper introduction to transaction propagation. Rather, it details some of the semantics regarding transaction propagation in Spring.
在 Spring 管理的事务中,请注意物理事务和逻辑事务之间的差异,以及传播设置如何应用于此差异。
In Spring-managed transactions, be aware of the difference between physical and logical transactions, and how the propagation setting applies to this difference.
Understanding PROPAGATION_REQUIRED

PROPAGATION_REQUIRED
强制执行物理事务,如果当前作用域中尚未存在事务,则强制执行本地事务,或者参与为更大作用域定义的现有“外部”事务。在同一线程中的调用栈常用排列中,这是一个很好的默认值(例如,将任务委托给几个存储库方法的服务外观,其中所有基础资源都必须参与服务级别事务)。
PROPAGATION_REQUIRED
enforces a physical transaction, either locally for the current
scope if no transaction exists yet or participating in an existing 'outer' transaction
defined for a larger scope. This is a fine default in common call stack arrangements
within the same thread (for example, a service facade that delegates to several repository methods
where all the underlying resources have to participate in the service-level transaction).
默认情况下,参与的事务将加入外部范围的特性,静默忽略本地隔离级别、超时值或只读标志(如果有)。如果您希望在参与具有不同隔离级别的现有事务时拒绝隔离级别声明,请考虑将 |
By default, a participating transaction joins the characteristics of the outer scope,
silently ignoring the local isolation level, timeout value, or read-only flag (if any).
Consider switching the |
当传播设置是 PROPAGATION_REQUIRED
时,将为应用该设置的每个方法创建一个逻辑事务作用域。每个这样的逻辑事务作用域可以单独确定回滚状态,而外部事务作用域在逻辑上独立于内部事务作用域。在标准 PROPAGATION_REQUIRED
行为的情况下,所有这些作用域都映射到同一个物理事务。因此,在内部事务作用域中设置的回滚状态标记确实会影响外部事务真正提交的机会。
When the propagation setting is PROPAGATION_REQUIRED
, a logical transaction scope
is created for each method upon which the setting is applied. Each such logical
transaction scope can determine rollback-only status individually, with an outer
transaction scope being logically independent from the inner transaction scope.
In the case of standard PROPAGATION_REQUIRED
behavior, all these scopes are
mapped to the same physical transaction. So a rollback-only marker set in the inner
transaction scope does affect the outer transaction’s chance to actually commit.
然而,在内部事务作用域设置回滚状态标记的情况下,外部事务尚未决定是否回滚,因此由内部事务作用域(无声触发)触发的回滚是意外的。这时会抛出相应的 UnexpectedRollbackException
。这是预期的行为,因此事务的调用者永远不会被误导为以为在实际没有提交的情况下执行了提交。因此,如果一个内部事务(外部调用者不知道)将事务无声地标记为仅回滚,则外部调用者仍然调用提交。外部调用者需要收到 UnexpectedRollbackException
才能明确指示已经执行了回滚。
However, in the case where an inner transaction scope sets the rollback-only marker, the
outer transaction has not decided on the rollback itself, so the rollback (silently
triggered by the inner transaction scope) is unexpected. A corresponding
UnexpectedRollbackException
is thrown at that point. This is expected behavior so
that the caller of a transaction can never be misled to assume that a commit was
performed when it really was not. So, if an inner transaction (of which the outer caller
is not aware) silently marks a transaction as rollback-only, the outer caller still
calls commit. The outer caller needs to receive an UnexpectedRollbackException
to
indicate clearly that a rollback was performed instead.
Understanding PROPAGATION_REQUIRES_NEW

与 PROPAGATION_REQUIRED
相反,PROPAGATION_REQUIRES_NEW
总是为每个受影响的事务作用域使用独立的物理事务,永远不会参与外部作用域的现有事务。在这样的安排中,底层资源事务是不同的,因此可以独立提交或回滚,外部事务不受内部事务回滚状态的影响,并且内部事务的锁在其完成之后立即释放。这样的独立内部事务还可以声明其自己的隔离级别、超时和只读设置,而不继承外部事务的特征。
PROPAGATION_REQUIRES_NEW
, in contrast to PROPAGATION_REQUIRED
, always uses an
independent physical transaction for each affected transaction scope, never
participating in an existing transaction for an outer scope. In such an arrangement,
the underlying resource transactions are different and, hence, can commit or roll back
independently, with an outer transaction not affected by an inner transaction’s rollback
status and with an inner transaction’s locks released immediately after its completion.
Such an independent inner transaction can also declare its own isolation level, timeout,
and read-only settings and not inherit an outer transaction’s characteristics.
连接至外部事务的资源将保持绑定状态,而内部事务获取它自己的资源,例如新的数据库连接。如果多个线程具有活动外部事务并等待为其内部事务获取新连接,这可能会导致连接池耗尽,并可能导致死锁,因为连接池无法再分配任何此类内部连接。除非您的连接池已适当调整大小,且至少比并发线程数多 1,否则请不要使用 |
The resources attached to the outer transaction will remain bound there while
the inner transaction acquires its own resources such as a new database connection.
This may lead to exhaustion of the connection pool and potentially to a deadlock if
several threads have an active outer transaction and wait to acquire a new connection
for their inner transaction, with the pool not being able to hand out any such inner
connection anymore. Do not use |
Understanding PROPAGATION_NESTED
PROPAGATION_NESTED
使用单个物理事务和可以回滚到多个保存点。这种部分回滚允许内部事务作用域触发其作用域的回滚,同时外部事务能够继续物理事务,而不管某些操作已被回滚。此设置通常映射到 JDBC 保存点,因此它仅适用于 JDBC 资源事务。请参阅 Spring 的https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/datasource/DataSourceTransactionManager.html[DataSourceTransactionManager
]。
PROPAGATION_NESTED
uses a single physical transaction with multiple savepoints
that it can roll back to. Such partial rollbacks let an inner transaction scope
trigger a rollback for its scope, with the outer transaction being able to continue
the physical transaction despite some operations having been rolled back. This setting
is typically mapped onto JDBC savepoints, so it works only with JDBC resource
transactions. See Spring’s DataSourceTransactionManager
.