Dopo settimane di test e lettura del codice sorgente di Django, ho trovato la risposta alla mia domanda:
transazioni
comportamento autocommit predefinito di Django è ancora valido per la mia funzione filettato. Tuttavia, si afferma nei documenti Django:
Non appena si esegue un'azione che deve scrivere nel database, Django produce le istruzioni INSERT/UPDATE/DELETE e quindi COMMIT. Non c'è ROLLBACK implicito.
Quest'ultima frase è molto letterale. NON emette un comando ROLLBACK a meno che qualcosa in Django non abbia impostato la flag dirty. Poiché la mia funzione stava facendo solo istruzioni SELECT, non ha mai impostato la flag dirty e non ha attivato un COMMIT.
Questo va contro il fatto che PostgreSQL pensa che la transazione richieda un ROLLBACK perché Django ha emesso un comando SET per il fuso orario. Nel rivedere i log, mi sono buttato fuori perché continuavo a vedere queste dichiarazioni ROLLBACK e ho assunto che la gestione delle transazioni di Django fosse la fonte. Si scopre che non lo è, e va bene.
Connessioni
La gestione connessione è dove le cose si fanno difficili. Django utilizza signals.request_finished.connect(close_connection)
per chiudere la connessione al database che normalmente utilizza. Dal momento che in Django non accade normalmente nulla che non implichi una richiesta, si dà per scontato questo comportamento.
Nel mio caso, tuttavia, non è stata richiesta perché il processo era pianificato. Nessuna richiesta significa nessun segnale. Nessun segnale significa che la connessione al database non è mai stata chiusa.
Tornando alle transazioni, si scopre che è sufficiente emettere una chiamata a connection.close()
in assenza di eventuali modifiche ai problemi di gestione delle transazioni dell'istruzione ROLLBACK nel registro PostgreSQL che stavo cercando.
Soluzione
La soluzione è quella di consentire il normale gestione delle transazioni Django procedere come normale e per chiudere semplicemente il collegamento uno dei tre modi:
- Scrivi un decoratore che chiude la connessione e avvolgere le funzioni necessarie in esso.
- Agganciare ai segnali di richiesta esistenti per fare in modo che Django chiuda la connessione.
- Chiudere la connessione manualmente alla fine della funzione.
Ognuno di questi tre lavori (e lo farà).
Questo mi ha fatto impazzire per settimane. Spero che questo aiuti qualcun altro in futuro!
Felice di averlo finalmente risolto. Non era ovvio. Mi chiedo se potrebbe valere un biglietto per aggiungere una nota nei documenti da qualche parte. –
Questo ticket descrive un problema molto simile: http://code.djangoproject.com/ticket/9964 – zooglash
Wow. qualche possibilità che tu possa condividere il codice? – Dejell