spring - Spring事务传播和隔离

标签 spring kotlin transactions isolation-level transaction-isolation

关于这个话题有很多问题。我已通过堆栈交换进行搜索,以查找与我的问题相同的问题,但未发现任何问题。如果已经问过这个问题,请原谅。

我的问题是:当使用Spring事务管理时,具有SERIALIZABLE隔离的事务方法调用另一个具有REQUIRES_NEW传播的事务方法时会发生什么?

据我了解,可序列化隔离意味着任何事务都将完全锁定表,直到完成为止。同时,REQUIRES_NEW将进行新交易并暂停现有交易。这意味着,由于父方法尚未完成其事务,因此它调用的方法将立即死锁。

我的理解错了吗?

为了说明这一点,我在Kotlin中做了一个示例,根据我的理解,该示例在 Spring 运行时即使没有出现错误也没有错误:

open class DummyApplication(val database: Database) {

    @Transactional(isolation = Isolation.SERIALIZABLE)
    open fun doThing() {

        val item = Item("1", "accountId1", "reference1")
        database.saveItemWithoutTransaction(item)

        val item2 = Item("2", "accountId2", "reference2")

        // This call should be instantly deadlocked because it tries to start a new transaction.
        database.saveItemWithTransaction(item2)

    }

}

和数据库:
@Repository
class JdbcDatabase(
        private val itemRepository: ItemRepository
) : Database {

    override fun saveItemWithoutTransaction(item: Item) {
        itemRepository.save(item.toItemEntity())
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    override fun saveItemWithTransaction(item: Item) {
        itemRepository.save(item.toItemEntity())
    }
}

itemRepository是一个Spring JPA存储库(如果相关)。

最佳答案

这取决于。

what happens when a transactional method with SERIALIZABLE isolation calls another transactional method with REQUIRES_NEW propagation?



您的问题比您的例子更为笼统。这就是答案取决于答案的原因。

A)如果第一个事务已更改任何内容,并且嵌套事务尝试更改同一表,并且嵌套事务的隔离度为READ_COMMITTED或更高(REPEATABLE_READ,SERIALIZABLE),则嵌套事务将被阻止。通常,阻塞(在这种情况下为死锁)发生在嵌套事务刷新其数据时。

B)如果在调用嵌套事务之前第一个事务未更改任何内容(在同一表中),并且嵌套事务的隔离是READ_COMMITTED或SERIALIZABLE,则嵌套事务不会被阻塞

C)如果第一个事务已更改任何内容,并且嵌套事务尝试更改同一表,并且嵌套事务的隔离为READ_UNCOMMITTED,则嵌套事务不会被阻止

您的示例对应于情况A。这就是为什么嵌套事务将被阻止并发生死锁的原因。

关于spring - Spring事务传播和隔离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58248605/

相关文章:

c# - SQL 服务器,C# : Timeout exception on Transaction Rollback

java - 如何使用 Spring 4.0.6 为 Hibernate 4.3.5.Final 全局设置 FlushMode?

java - 如何摆脱 Spring Boot 中的 JpaRepository 接口(interface)

spring - java :comp/env point to?在哪里

mysql - MySQL 事务可以与事件调度程序一起使用吗?

nhibernate - 刷新 NHibernate,同时仍然允许事务回滚

java - Servlet 不应该有可变的实例字段误报 Spring Autowiring (squid :S2226)

android - 抽屉导航用另一个有问题的保留抽屉选项的 fragment 替换 fragment

kotlin - 协程范围的构造函数中的协程上下文的Kotlin组成

java - 在springboot上使用elasticsearch查询