2010-07-09 14 views
5

Come metodo django save() metodi are not lazy e poiché mantenere le transazioni brevi è una buona pratica generale, i salvataggi dovrebbero preferibilmente essere posticipati alla fine dei blocchi di transazione?Django - Keeping save() transazioni basate short

Ad esempio, il codice di esempio B mantiene una transazione aperta per meno tempo rispetto al codice di esempio A di seguito?

campione

Codice 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() 

Esempio di codice 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() 

risposta

1

Il comportamento predefinito di Django è quello di eseguire una transazione aperta che viene commutata automaticamente quando viene chiamata una funzione del modello incorporata che modifica i dati. In caso di commit_on_success o commit_manually decorators, django non si impegna su save(), ma su esecuzione della funzione completata correttamente o sul comando transaction.commit() rispettivamente.

Pertanto, l'approccio elegante sarebbe quella di separare il codice di transazione movimentazione e altro codice che richiede tempo, se possibile:

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) 

Se questa è la progettazione impossibile saggio, per esempio hai bisogno di instance.id informazioni che per le nuove istanze si possono ottenere solo dopo il primo save(), prova a suddividere il flusso in workbase di dimensioni ragionevoli, in modo da non mantenere la transazione aperta per lunghi minuti.

Si noti inoltre che avere transazioni lunghe non è sempre una cosa negativa. Se la tua applicazione è l'unica entità che modifica il db, potrebbe effettivamente essere ok. Dovresti comunque controllare la configurazione specifica del tuo db per vedere il limite di tempo per le transazioni (o la transazione inattiva).

3

Non sono sicuro, ma qui è la mia teoria - Vorrei pensare che il vostro decoratore commit_manually inizierà una nuova transazione piuttosto che avere una nuova transazione nasce quando fai il tuo primo salvataggio. Quindi la mia teoria è che l'esempio di codice B manterrebbe la transazione aperta più a lungo, dal momento che deve scorrere l'elenco dei modelli due volte.

Ancora una volta, questa è solo una teoria - e potrebbe anche dipendere da quale DBMS si sta utilizzando quando inizia la transazione effettiva (un'altra teoria).

+1

In molti casi, la preparazione dei dati per una transazione richiede molto tempo. Se come dici tu, la transazione viene aperta non appena inizia il blocco decorato, quindi c'è una motivazione per separare blocchi di preparazione e blocchi di transazione ... Se questo è il caso, allora dovrebbe essere documentato nella documentazione di django nella sezione delle transazioni . – Jonathan

Problemi correlati