CodeGym /Cours /SQL SELF /Erreurs typiques lors du travail avec les transactions

Erreurs typiques lors du travail avec les transactions

SQL SELF
Niveau 40 , Leçon 4
Disponible

Dans ce cours, on va se concentrer sur les erreurs classiques qui arrivent quand tu manipules des transactions, et comment les esquiver. Franchement, même le plus balèze des SQL-geeks oublie parfois de mettre un COMMIT ! On va te filer des astuces pour que les fails de transactions deviennent super rares.

Malheureusement (ou heureusement ?), les bases de données, c’est pas un château magique où tout roule tout le temps. Les erreurs avec les transactions, c’est super fréquent, surtout quand tu débutes. Allez, on va les décortiquer ensemble.

Oubli de la commande COMMIT ou ROLLBACK

Oublier de finir une transaction, c’est vraiment le “classique du genre”. Imagine un resto où t’as commandé ton plat, mais le serveur a zappé de t’apporter l’addition. Dans le monde de PostgreSQL, ça veut dire que la base “reste bloquée” en mode transaction, elle garde les ressources et bloque les autres opérations.

Exemple d’erreur :

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- Oups ! On a oublié d’ajouter COMMIT ou ROLLBACK.

Quand une transaction “reste bloquée”, le lock peut s’étendre à toute la table. Si l’admin de la base sent que ça part en vrille, il peut la terminer à la dure. Mais franchement, vaut mieux pas en arriver là.

Comment éviter ça ?

  • Termine toujours ta transaction explicitement : COMMIT ou ROLLBACK.
  • Utilise des outils clients qui te rappellent automatiquement les transactions bloquées.
  • Si la transaction n’est pas finie et que tu relances l’appli, la base va faire un ROLLBACK auto, mais c’est pas toujours top pour l’état du système.

Utilisation d’un mauvais niveau d’isolation

Choisir le niveau d’isolation, ça peut sembler relou, mais c’est super important pour éviter les anomalies. Par exemple, si tu utilises READ UNCOMMITTED pour une opération financière critique, tu risques de lire des “données sales” qui peuvent être annulées après.

Exemple :

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN;
-- On lit des données qui sont modifiées par une autre transaction
SELECT balance FROM accounts WHERE account_id = 1;
-- Une autre transaction va faire ROLLBACK, et tes données seront invalides.

Comment éviter ça ?

  • Définis à quel point les données sont importantes pour ton appli.
  • Utilise READ COMMITTED dans la plupart des cas pour éviter la lecture de “données sales”.
  • Prends des niveaux d’isolation plus stricts REPEATABLE READ, SERIALIZABLE pour les opérations où tu veux vraiment éviter les changements ou les “phantom reads”.

Conflit de transactions et locks

Parfois, deux transactions (ou plus) essaient de modifier les mêmes données. Dans ce cas, PostgreSQL va en bloquer une jusqu’à ce que l’autre soit finie. Ça peut mener à un deadlock (blocage mutuel).

Exemple d’erreur :

-- Première transaction
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;

-- Deuxième transaction
BEGIN;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 1;
-- En attente de la première transaction...

Si les deux transactions gardent des ressources dont l’autre a besoin, c’est le deadlock assuré. PostgreSQL va le détecter, tuer une des transactions avec une erreur et afficher :

ERROR: deadlock detected

Comment éviter ça ?

  • Suis toujours le même ordre d’opérations dans tes transactions.
  • Réduis au max la durée de tes transactions pour limiter les risques de lock.
  • Utilise le niveau d’isolation SERIALIZABLE seulement si c’est vraiment nécessaire.

Erreur avec SAVEPOINT

SAVEPOINT, c’est super pratique pour faire des rollbacks partiels, mais mal utilisé, ça peut vite devenir le bazar. Par exemple, si tu oublies de libérer un point de sauvegarde (RELEASE SAVEPOINT), tu risques des locks inutiles ou des erreurs.

Exemple d’erreur :

BEGIN;
SAVEPOINT my_savepoint;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
ROLLBACK TO SAVEPOINT my_savepoint;
-- On a oublié de libérer le SAVEPOINT !

Comment éviter ça ?

  • Assure-toi de supprimer le SAVEPOINT s’il ne sert plus à rien.
  • Évite d’en créer trop, sinon tes requêtes vont devenir trop complexes.

Incompatibilité des transactions avec les systèmes externes

Imagine qu’une transaction dans PostgreSQL essaie de causer avec des systèmes externes : envoyer des notifs, mettre à jour une API, etc. Si un truc foire côté externe, c’est galère de revenir en arrière.

Exemple :

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- Impossible d’envoyer la notif : le serveur email ne répond pas.
COMMIT; -- Les changements sont sauvegardés, mais la notif n’est pas partie.

Comment éviter ça ?

  • Si possible, isole les opérations avec les systèmes externes.
  • Utilise des tables intermédiaires ou des files de tâches pour coordonner avec les systèmes externes.

Erreurs à cause de transactions trop grosses

Les grosses transactions avec plein d’opérations sont plus fragiles : locks, timeouts, deadlocks, tout ça.

Exemple :

BEGIN;
-- Plusieurs milliers d’opérations d’update
UPDATE orders SET status = 'completed' WHERE delivery_date < CURRENT_DATE;
COMMIT; -- Ça peut prendre un temps fou.

Comment éviter ça ?

  • Découpe les grosses transactions en plusieurs plus petites.
  • Utilise des batchs pour mettre à jour les données.
  • Réduis au max le volume de données modifiées dans une seule transaction.

Oubli de la gestion des erreurs

Toutes les requêtes SQL dans une transaction ne vont pas forcément marcher. Par exemple, si une opération plante, toute la transaction part en échec.

Exemple :

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_id = -1; -- Erreur : account_id n’existe pas.
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
COMMIT; -- Ne s’exécute pas à cause de l’erreur.

Comment éviter ça ?

  • Vérifie toujours le résultat de chaque opération.
  • Gère les erreurs dans tes requêtes ou dans ton code client.

Mauvaise compréhension du comportement de ROLLBACK

Plein de devs pensent que ROLLBACK annule tout et remet tout à zéro. Mais ROLLBACK ne marche que dans la transaction en cours.

Exemple de malentendu :

UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
ROLLBACK; -- Erreur ! Ça marche pas, car l’opération n’était pas dans une transaction.

Comment éviter ça ?

  • Souviens-toi : BEGIN est ton pote, sans lui ROLLBACK ne sert à rien.
  • Enveloppe toujours les opérations critiques dans des transactions.
1
Étude/Quiz
Introduction aux niveaux d'isolation des transactions, niveau 40, leçon 4
Indisponible
Introduction aux niveaux d'isolation des transactions
Introduction aux niveaux d'isolation des transactions
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION