Распространение и изоляция транзакций Spring - PullRequest
2 голосов
/ 05 октября 2019

На эту тему много вопросов. Я искал обмен стека, чтобы найти вопрос, который является таким же, как мой, но не нашел ни одного. Пожалуйста, извините, если этот вопрос уже задавался.

Мой вопрос: при использовании управления транзакциями Spring, что происходит, когда транзакционный метод с изоляцией SERIALIZABLE вызывает другой транзакционный метод с распространением REQUIRES_NEW?

Насколько я понимаю, сериализуемая изоляция означает, что любаятранзакция полностью заблокирует таблицу, пока она не будет завершена. Между тем, REQUIRES_NEW совершит новую транзакцию и приостановит существующую. Это означает, что, поскольку родительский метод еще не завершил свою транзакцию, вызываемый им метод будет мгновенно заблокирован.

Правильно ли мое понимание здесь?

Для иллюстрации я сделал пример вKotlin, который работает без ошибок весной, хотя и не должен, по моему мнению:

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, если это уместно.

1 Ответ

1 голос
/ 05 октября 2019

Это зависит.

что происходит, когда транзакционный метод с изоляцией SERIALIZABLE вызывает другой транзакционный метод с распространением REQUIRES_NEW?

Ваш вопрос гораздо более общий чем ваш пример. Поэтому ответ зависит .

A) Если первая транзакция изменила что-либо и , вложенная транзакция пытается изменить ту же таблицу и изоляция вложенной транзакции равна READ_COMMITTED или выше (REPEATABLE_READ, SERIALIZABLE), тогда вложенная транзакция будет заблокирована . Обычно блокировка (в данном случае взаимоблокировка) происходит в момент, когда вложенная транзакция сбрасывает свои данные.

B) Если первая транзакция ничего не изменила (в той же таблице) перед вызовом вложенной транзакции и изоляция вложенной транзакции READ_COMMITTED или SERIALIZABLE, тогда вложенная транзакция не будет заблокирована .

C) Если первая транзакция изменила что-либо и вложенная транзакция пытается изменить ту же таблицу и изоляция вложенной транзакции - READ_UNCOMMITTED, тогда вложенная транзакция не будет заблокирована .

Вашапример соответствует случаю А. Поэтому вложенная транзакция будет заблокирована и возникнет взаимоблокировка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...