关于这个话题有很多问题。我已通过堆栈交换进行搜索,以查找与我的问题相同的问题,但未发现任何问题。如果已经问过这个问题,请原谅。
我的问题是:当使用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/