Il existe deux façons d'imbriquer des transactions dans SQLAlchemy. L'un est les transactions virtuelles, où SQLAlchemy garde la trace du nombre de début que vous avez émis et émet la validation uniquement lorsque la transaction la plus externe est validée. La restauration est toutefois émise immédiatement. Comme la transaction est virtuelle, c'est-à-dire que la base de données ne connaît rien de l'imbrication, vous ne pouvez rien faire avec cette session après l'annulation jusqu'à ce que vous annuliez toutes les transactions externes. Pour autoriser l'utilisation des transactions virtuelles, ajoutez l'argument subtransactions=True
à l'appel begin()
. Cette fonctionnalité existe pour vous permettre d'utiliser le contrôle des transactions dans des fonctions qui pourraient s'appeler sans suivre si vous êtes dans une transaction ou non. Pour que cela ait du sens, configurez la session avec autocommit=True
et émettez toujours un session.begin(subtransactions=True)
dans une fonction transactionnelle.
L'autre manière d'imbriquer des transactions consiste à utiliser des transactions réelles imbriquées. Ils sont implémentés en utilisant des points de sauvegarde. Si vous annulez une transaction imbriquée, toutes les modifications effectuées au sein de cette transaction sont annulées, mais la transaction externe reste utilisable et toutes les modifications apportées par la transaction externe sont toujours présentes. Pour utiliser le numéro de transaction imbriqué session.begin(nested=True)
ou simplement session.begin_nested()
. Les transactions imbriquées ne sont pas prises en charge pour toutes les bases de données. La fonction de configuration de la bibliothèque de suite de tests de SQLAlchemy sqlalchemy.test.requires.savepoints
dit ceci au sujet du support:
emits_warning_on('mssql', 'Savepoint support in mssql is experimental and may lead to data loss.'),
no_support('access', 'not supported by database'),
no_support('sqlite', 'not supported by database'),
no_support('sybase', 'FIXME: guessing, needs confirmation'),
exclude('mysql', '<', (5, 0, 3), 'not supported by database')
sur les transactions imbriquées PostgreSQL sqlalchemy fonctionnent très bien.
Les transactions imbriquées (par exemple AUTONOMOUS_TRANSACTION d'Oracle) sont considérées comme un anti-pattern hormis deux cas: Audit (la tentative est auditée même si l'instruction est annulée) et Error Logging (pour capturer où/quand des échecs existent). Tous les autres cas doivent utiliser des points de sauvegarde. Heck, la portée de la transaction n'appartient à aucune fonction ou procédure; Ce devrait être la responsabilité ultime de l'appelant de s'engager ou de revenir en arrière. –
C'est une transception. – user