PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Quelles exceptions spécifiques représentent un échec de sérialisation lorsque Django utilise le niveau d'isolation de transaction sérialisable avec postgresql ?

Hum, bonne question. La documentation implique que l'exception appropriée serait une TransactionManagementError :

Cependant, le code source donne un indice fort que ce n'est pas :

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

Notez qu'il s'agit d'une ProgrammingError , qui est en effet utilisé pour indiquer une erreur du programmeur (c'est-à-dire "utilisé de manière incorrecte").

Si nous regardons la documentation de psycopg (l'adaptateur Python utilisé pour le support de PostgreSQL), nous voyons qu'il lèvera un psycopg2.extensions.TransactionRollbackError :

Mais que fait Django avec ça ? Eh bien, comme documenté ici , il encapsule les exceptions standard Python DB API 2.0 dans les équivalents Django et définit le __cause__ attribut à l'exception d'origine. La vérification suivante est donc probablement la plus spécifique que vous puissiez effectuer :

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

Selon les détails de l'erreur exposés par PostgreSQL (disponible via e.__cause__.diag ) il peut être possible d'écrire un test encore plus spécifique.

Généralement, cependant, la documentation Python DB API 2.0 indique que OperationalError est en effet le type d'exception correct pour les problèmes de transaction, donc l'attraper serait, espérons-le, une solution raisonnablement efficace et indépendante de la base de données.