Подтвердить что ты не робот

Является ли "transaction.atomic" таким же, как "transaction.commit_on_success"?

Django 1.6 предлагает @transaction.atomic как часть ремонта в управлении транзакциями от 1.5.

У меня есть функция, которая вызывается командой управления Django, которая, в свою очередь, называется cron, т.е. никаких запросов HTTP-запроса при запуске транзакций в этом случае. Отрывок:

from django.db import transaction

@transaction.commit_on_success
def my_function():
    # code here

В приведенном выше блоке кода commit_on_success использует одну транзакцию для всей работы, выполненной в my_function.

Выполняет ли замена @transaction.commit_on_success на @transaction.atomic одинаковое поведение? @transaction.atomic docs state:

Атомность - определяющее свойство транзакций базы данных. атомное позволяет нам создать блок кода, в котором атомарность на база данных гарантирована. Если блок кода успешно завершены изменения, внесенные в базу данных. Если есть исключение, изменения откатываются.

Я считаю, что они приводят к такому же поведению; правильно?

4b9b3361

Ответ 1

Да. Вы должны использовать atomic в тех местах, где вы ранее использовали commit_on_success.

Так как новая транзакционная система спроектирована так, чтобы быть более надежной и последовательной, возможно, вы могли видеть другое поведение. Например, если вы поймаете ошибки базы данных и попытаетесь продолжить, вы увидите TransactionManagementError, тогда как предыдущее поведение было undefined и, вероятно, зависящим от случая.

Но если вы делаете все правильно, все должно продолжать работать одинаково.

Ответ 2

Основываясь на документации, которую я прочитал по этому вопросу, существует значительная разница, когда эти декораторы вложены.

Вложение двух блоков atomic не работает так же, как вложение двух блоков commit_on_success.

Проблема в том, что есть две гарантии, которые вы хотели бы иметь из этих блоков.

  • Вы хотите, чтобы содержимое блока было атомарным, либо все внутри блока зафиксировано, либо ничего не сделано.
  • Вы хотели бы долговечность, как только вы покинули блок без исключения, вам гарантировано, что все, что вы написали внутри блока, является постоянным.

Невозможно предоставить обе гарантии, когда блоки вложены. Если исключение возникает после выхода из самого внутреннего блока, но перед выходом из внешнего блока вам придется сбой одним из двух способов:

  • Невозможно обеспечить долговечность самого внутреннего блока.
  • Невозможно обеспечить атомарность для внешнего блока.

Здесь вы найдете разницу. Использование commit_on_success обеспечило бы прочность для самого внутреннего блока, но без атомарности для самого внешнего блока. Использование atomic даст атомарность для самого внешнего блока, но не долговечность для самого внутреннего блока.

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

Лучшим решением было бы получить более подробную информацию о том, что вы просите. Если вы можете отдельно задавать атомарность и долговечность, вы можете выполнить вложенность. Вам просто нужно убедиться, что каждый блок, требующий долговечности, находится за пределами тех, кто требует атомарности. Требование прочности внутри блока, запрашивающего атомарность, должно было бы вызвать исключение.

atomic должен обеспечивать часть атомарности. Насколько я могу судить, django 1.6.1 не имеет декоратора, который может просить о прочности. Я попытался написать один, и опубликовал его на codereview.