Django - сокращение транзакций на основе save () - PullRequest
5 голосов
/ 09 июля 2010

Поскольку методы save () модели django не являются ленивыми , и, поскольку сохранение коротких транзакций является общепринятой практикой, следует ли откладывать сохранение предпочтительно до конца блоков транзакций?

КакНапример, будет ли образец кода B держать транзакцию открытой в течение меньшего времени, чем образец кода A ниже?

Пример кода A:

from django.db import transaction
from my_app.models import MyModel

@transaction.commit_on_success
def model_altering_method():
    for inst in MyModel.objects.all()[0:5000]:
        inst.name = 'Joel Spolsky'
        # Some models independent time consuming operations...
        inst.save()

Пример кода B:

from django.db import transaction
from my_app.models import MyModel

@transaction.commit_on_success
def model_altering_method():
    instances_to_save = []
    for inst in MyModel.objects.all()[0:5000]:
        inst.name = 'Joel Spolsky'
        # Some models independent time consuming operations...
        instances_to_save.append(inst)

    for inst in instances_to_save:
        inst.save()

Ответы [ 2 ]

3 голосов
/ 10 июля 2010

Я не уверен, но вот моя теория - я думаю, что ваш декоратор commit_manually начнет новую транзакцию вместо того, чтобы новая транзакция возникла при первом сохранении. Так что моя теория заключается в том, что образец кода B будет держать транзакцию открытой дольше, поскольку он должен дважды просматривать список моделей.

Опять же, это всего лишь теория - и она также может зависеть от того, какую СУБД вы используете, когда начинается фактическая транзакция (другая теория).

1 голос
/ 16 июля 2010

По умолчанию Django работает с открытой транзакцией, которую он фиксирует автоматически при вызове любой встроенной функции, изменяющей данные.В случае декораторов commit_on_success или commit_manually django фиксирует не после save (), а при успешном завершении выполнения функции или при выполнении командыaction.commit () соответственно.

Следовательно, элегантный подход заключается в разделенииКод обработки транзакций и другой трудоемкий код, если это возможно:

from django.db import transaction
from my_app.models import MyModel

@transaction.commit_on_success
def do_transaction(instances_to_save):
    for inst in instances_to_save:
        inst.save()

def model_altering_method():
    instances_to_save = []
    for inst in MyModel.objects.all()[0:5000]:
        inst.name = 'Joel Spolsky'
        # Some models independent time consuming operations...
        instances_to_save.append(inst)
    do_transaction(instances_to_save)

Если это невозможно с точки зрения дизайна, например, вам нужна информация instance.id, которую для новых экземпляров вы можете получить только после первого save (),попробуйте разбить поток на рабочие блоки разумного размера, чтобы не оставлять транзакцию открытой в течение долгих минут.

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

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