2010-07-09 23 views
5

Jako metody django model save() are not lazy, a jako zachowanie krótkich transakcji jest ogólną dobrą praktyką, powinny być zapisywane najlepiej odroczone do końca bloków transakcji?Django - Przechowywanie transakcji opartych na save() Krótki

Przykładowy przykład kodu B może zawierać transakcję otwartą krócej niż przykład kodu A poniżej?

Kod próbka 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() 

przykładowy kod 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() 

Odpowiedz

1

Domyślne zachowanie Django polega na uruchomieniu z otwartą transakcją, którą zatwierdza automatycznie po wywołaniu dowolnej wbudowanej funkcji modelu zmieniającej dane. W przypadku commit_on_success lub commit_manually decorators, django nie działa po save(), ale raczej po pomyślnym zakończeniu wykonywania funkcji lub po poleceniu transaction.commit().

Dlatego eleganckim rozwiązaniem byłoby oddzielić kod obsługi transakcji i innym momencie kod czasochłonne jeśli to możliwe:

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) 

Jeśli jest to niemożliwe, projektowanie mądry, np potrzebujesz informacji typu instance.id, które dla nowych instancji można uzyskać tylko po pierwszym zapisaniu(), spróbuj podzielić swój przepływ na workunity o rozsądnej wielkości, aby nie utrzymywać transakcji otwartej przez długie minuty.

Należy również zauważyć, że posiadanie długich transakcji nie zawsze jest złą rzeczą. Jeśli twoja aplikacja jest jedyną jednostką modyfikującą bazę danych, może to być w porządku. Powinieneś jednak sprawdzić konkretną konfigurację swojej bazy danych, aby zobaczyć limit czasowy dla transakcji (lub bezczynnej transakcji).

3

Nie jestem pewien, ale tutaj jest moja teoria - to myślę, że commit_manually dekorator rozpocznie nową transakcję zamiast otwierać nową transakcję, gdy robisz pierwszy zapis. Tak więc moja teoria mówi, że próbka kodu B zatrzymałaby transakcję dłużej, ponieważ musi dwukrotnie przeglądać listę modeli.

Ponownie, to tylko teoria - i może również zależeć od tego, którego DBMS używasz, kiedy zaczyna się faktyczna transakcja (inna teoria).

+1

W wielu przypadkach przygotowanie danych do transakcji zajmuje dużo czasu. Jeśli powiesz, że transakcja zostanie otwarta zaraz po rozpoczęciu dekorowanego bloku, to jest motywacja do oddzielenia bloków przygotowawczych i bloków transakcji ... Jeśli tak jest, to powinna być udokumentowana w dokumentacji django w sekcji transakcji . – Jonathan

Powiązane problemy