Gestion des transactions

De RAD Studio
Aller à : navigation, rechercher

Remonter à Connexion aux bases de données - Index


Une transaction est un groupe d'actions qui doivent être menées avec succès sur une ou plusieurs tables dans une base de données avant d'être validées (rendues définitives). Si l'une des actions du groupe échoue, toutes les actions sont annulées (abandonnées). Les transactions préservent l'homogénéité de la base de données en cas d'occurrence d'un problème suite à l'exécution d'une des actions qui les composent.

Par exemple, dans une application bancaire, le transfert de fonds d'un compte vers un autre est une opération qui mérite d'être protégée avec une transaction. Si, après diminution du solde d'un compte, une erreur se produit dans l'augmentation du solde de l'autre compte, il est souhaitable d'annuler la transaction afin que la base de données continue de refléter le solde total correct.

Il est toujours possible de gérer les transactions par émission directe de commandes SQL à la base de données. A l'exception de certaines bases de données qui n'offrent aucune prise en charge des transactions, la plupart des bases de données fournissent leur propre modèle de gestion des transactions. Si votre serveur de base de données le permet, vous pouvez coder directement votre propre gestion des transactions afin de tirer parti des fonctionnalités avancées de gestion des transactions, telles que la mise en mémoire cache des schémas.

Si vous n'avez pas besoin d'utiliser de fonctionnalités avancées, les composants connexion fournissent un ensemble de méthodes et de propriétés permettant de gérer les transactions sans explicitement émettre de commande SQL. Grâce à ces propriétés et méthodes, vous n'avez pas besoin de personnaliser votre application en fonction de chaque type de serveur de base de données utilisé, sous réserve que le serveur prenne en charge les transactions. (Le moteur BDE offre également une prise en charge limitée des transactions pour les tables locales sans prise en charge des transactions du serveur. Lorsque le moteur BDE n'est pas utilisé, toute tentative de démarrage de transactions sur une base de données qui ne les prend pas en charge amène les composants connexion à déclencher une exception.)

Avertissement :  Lorsqu'un composant fournisseur d'ensemble de donnéesapplique des mises à jour, il génère implicitement les transactions pour toutes les mises à jour. Veillez à ce que toutes les transactions explicitement démarrées n'entrent pas en conflit avec celles générées par le fournisseur.

Démarrage d'une transaction

Lorsque vous démarrez une transaction, toutes les instructions suivantes qui réalisent des opérations de lecture ou d'écriture sur la base de données interviennent dans le contexte de cette transaction jusqu'à ce que la transaction soit achevée de façon explicite ou, dans le cas de transactions se chevauchant, jusqu'à ce qu'une autre transaction soit démarrée. Chaque instruction est considérée comme faisant partie d'un groupe. Si les modifications ne sont pas validées avec succès dans la base de données, chaque modification apportée dans le groupe doit être annulée.

Lorsque la transaction est en cours de traitement, la vue des données des tables de la base de données est déterminée par le niveau d'isolement des transactions.

Pour TADOConnection, démarrez une transaction en appelant la méthode BeginTrans

 Level := ADOConnection1.BeginTrans;

BeginTrans renvoie le niveau d'imbrication de la transaction démarrée. Une transaction imbriquée est une transaction qui fait partie d'une autre transaction parent. Une fois que le serveur a démarré la transaction, la connexion ADO reçoit un événement OnBeginTransComplete.

Pour TDatabase, utilisez la méthode StartTransaction. TDataBase ne prend pas en charge les transactions imbriquées ou se chevauchant : Si vous appelez la méthode StartTransaction du composant TDatabase alors qu'une autre transaction est en cours, une exception est déclenchée. Pour éviter d'appeler StartTransaction, vous pouvez vérifier la propriété InTransaction :

 if not Database1.InTransaction then
   Database1.StartTransaction;

TSQLConnection utilise également la méthode StartTransaction, dans une version qui offre davantage de contrôle. Notamment, StartTransaction accepte un descripteur de transaction qui permet de gérer plusieurs transactions simultanées et de spécifier le niveau d'isolement des transactions pour chaque transaction. Pour gérer plusieurs transactions simultanées, attribuez au champ TransactionID du descripteur de transaction une valeur unique. TransactionID peut prendre n'importe quelle valeur, sous réserve qu'elle soit unique (c'est-à-dire non conflictuelle avec une transaction en cours). Suivant le serveur, les transactions démarrées par TSQLConnection peuvent être imbriquées (comme dans le cas d'une connexion ADO) ou se chevaucher.

 var
   TD: TTransactionDesc;
 begin
   TD.TransactionID := 1;
   TD.IsolationLevel := xilREADCOMMITTED;
   SQLConnection1.StartTransaction(TD);

Par défaut, dans le cas des transactions se chevauchant, la première transaction devient inactive lorsque la seconde démarre, bien que vous puissiez différer la validation ou l'annulation de la première. Si vous utilisez TSQLConnection avec une base de données InterBase, vous pouvez identifier chaque ensemble de données dans votre application avec une transaction active particulière, en définissant sa propriété IsolationLevel. En d'autres termes, après le démarrage d'une seconde transaction, vous pouvez continuer à utiliser les deux transactions simultanément, en associant simplement un ensemble de données à la transaction qui vous intéresse.

Remarque :  Contrairement à TADOConnection, TSQLConnection et TDatabase ne reçoivent pas d'événements au démarrage des transactions.

InterBase Express offre davantage de contrôle que TSQLConnection en utilisant un composant transaction distinct au lieu de démarrer les transactions au moyen du composant connexion. Vous pouvez, toutefois, utiliser TIBDatabase pour démarrer une transaction par défaut

 if not IBDatabase1.DefaultTransaction.InTransaction then
   IBDatabase1.DefaultTransaction.StartTransaction;

Vous pouvez obtenir des transactions se chevauchant à l'aide de deux composants transaction séparés. Chaque composant transaction possède un ensemble de paramètres qui permettent de configurer les propriétés de la transaction. Ces paramètres vous permettent de spécifier le niveau d'isolement, ainsi que d'autres propriétés de la transaction.

Achèvement d'une transaction

Au mieux, une transaction ne doit durer que le temps nécessaire. Plus une transaction demeure active, plus d'utilisateurs peuvent simultanément accéder à la base de données. De même, plus nombreuses sont les transactions qui démarrent et s'achèvent simultanément pendant la durée de vie de votre transaction, plus grande est la probabilité pour que votre transaction entre en conflit avec une autre transaction lorsque vous essayez de valider vos modifications.

Lorsque les actions qui composent la transaction ont toutes réussi, vous pouvez rendre définitives les modifications de la base de données en validant la transaction. Dans le cas de TDatabase, vous validez une transaction à l'aide de la méthode Commit

 MyOracleConnection.Commit;

Dans le cas de TSQLConnection, vous utilisez également la méthode Commit, mais vous devez spécifier la transaction à valider en fournissant le descripteur de transaction communiqué à la méthode StartTransaction

 MyOracleConnection.Commit(TD);

Dans le cas de TIBDatabase, vous validez un objet transaction à l'aide de sa méthode Commit

 IBDatabase1.DefaultTransaction.Commit;

Dans le cas de TADOConnection, vous validez une transaction à l'aide de la méthode CommitTrans

 ADOConnection1.CommitTrans;

Remarque :  Il est possible de valider une transaction imbriquée de sorte que seules les modifications ultérieures soient annulées si la transaction parent est annulée.

Une fois la transaction correctement validée, un composant connexion ADO reçoit un événement OnCommitTransComplete. Les autres composants connexion ne reçoivent pas d'événements similaires.

Un appel pour valider la transaction en cours est généralement tenté dans une instruction try...except. Ainsi, si une transaction ne peut pas être correctement validée, vous pouvez utiliser le bloc except pour traiter l'erreur et renouveler l'opération ou pour annuler la transaction.

Si une erreur se produit pendant l'application des modifications faisant partie de la transaction ou pendant la tentative de validation de la transaction, vous pouvez supprimer toutes les modifications qui composent la transaction. La suppression de ces modifications correspond à l'annulation de la transaction.

Dans le cas de TDatabase, vous annulez une transaction en appelant la méthode Rollback

 MyOracleConnection.Rollback;

Dans le cas de TSQLConnection, vous utilisez également la méthode Rollback, mais vous devez spécifier la transaction à annuler en fournissant le descripteur de transaction communiqué à la méthode StartTransaction

 MyOracleConnection.Rollback(TD);

Dans le cas de TIBDatabase, vous annulez un objet transaction en appelant sa méthode Rollback

 ADOConnection1.RollbackTrans;

Dans le cas de TADOConnection, vous annulez une transaction en appelant la méthode RollbackTrans

 ADOConnection1.RollbackTrans;

Une fois la transaction correctement annulée, un composant connexion ADO reçoit un événement OnRollbackTransComplete. Les autres composants connexion ne reçoivent pas d'événements similaires.

Un appel pour annuler la transaction en cours se produit généralement

  • Dans un code de gestion des exceptions, lorsque vous ne pouvez pas rétablir la situation après une erreur de base de données.
  • Dans un code d'événement de bouton ou de menu, comme lorsqu'un utilisateur clique sur un bouton Annuler.

Voir aussi