PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Quali eccezioni specifiche rappresentano un errore di serializzazione quando Django utilizza il livello di isolamento della transazione serializzabile con postgresql?

Hmm, bella domanda. La documentazione implica che l'eccezione appropriata sarebbe un TransactionManagementError :

Tuttavia, il codice sorgente dà un forte indizio che non lo è:

class TransactionManagementError(ProgrammingError):
    """Transaction management is used improperly."""
    pass

Tieni presente che questo è un ProgrammingError , che in effetti viene utilizzato per indicare un errore del programmatore (ovvero "usato in modo improprio").

Se osserviamo la documentazione per psycopg (l'adattatore Python utilizzato per il supporto di PostgreSQL) vediamo che genererà un psycopg2.extensions.TransactionRollbackError :

Ma cosa ci fa Django con quello? Bene, come documentato qui , racchiude le eccezioni standard Python DB API 2.0 negli equivalenti di Django e imposta il __cause__ attribuire all'eccezione originale. Quindi il seguente è probabilmente il controllo più specifico che puoi effettuare:

from django.db import OperationalError
from psycopg2.extensions import TransactionRollbackError

for retries in range(0, 3):
    try:
        with transaction.atomic():
            MyModel.objects.update(foo='bar')
    except OperationalError as e:
        if e.__cause__.__class__ == TransactionRollbackError:
            continue
        else:
            raise            
    else:
        break

A seconda dei dettagli dell'errore esposti da PostgreSQL (disponibile tramite e.__cause__.diag ) potrebbe essere possibile scrivere un test ancora più specifico.

In genere, tuttavia, la documentazione Python DB API 2.0 afferma che OperationalError è davvero il tipo di eccezione corretto per i problemi di transazione, quindi catturarlo si spera sia una soluzione indipendente dal database ragionevolmente efficace.