Bonjour,
Je modélise un système de réservation en PHP + PostGreSQL.
Je n'arrive pas à trouver de solution propre pour un problème d'accès concurrents.
Description de mon problème:
J'ai un système de réservation dans lequel une réservation pour une personne vaut un coupon.
Pour réserver pour n personnes l'utilisateur doit utiliser n coupons.
Une table représente les achats de coupons: achat_coupon.
Une autre table représente les remboursements de coupons: remboursement_coupon.
Une autre table représente les paiements des réservations (utilisation de coupons): paiement_reservation.
Pour connaître le solde de coupons je fais la somme des achats de coupons - la somme des paiements de réservations (utilisation de coupons) - les remboursements de coupon.
Contrainte: Le solde doit toujours être positif.
Avant de finaliser une réservation je vérifie qu'il y a assez de coupons pour l'effectuer (grâce à l'opération de calcul du solde).
Problème:
Lorsque je finalise la réservation en enregistrant un nouveau paiement de réservation, rien ne m'assure qu'aucun changement dans les tables achat_coupon et surtout remboursement_coupon n'a été effectué en parallèle. Donc mon solde pourrait être négatif à l'issue de cette opération.
Plusieurs solutions auxquelles j'ai pensé:
(1) Vérifier a posteriori que le solde est positif et annuler le paiement de réservation (DELETE) si solde négatif. C'est bourrin et pas forcément safe si jamais j'ai une exception ou un crash de la BDD avant de faire la vérification. Mon paiement serait alors enregistré alors que le solde est négatif.
(2) Utiliser les transactions pour effectuer le paiement puis la vérification a posteriori. Cela permet de rendre l'opération atomique. Donc je n'ai plus le problème d'exception ou de crash en plein milieu d'une opération. Tant que ce n'est pas commité rien n'est enregistré en BDD.
Problème: même en SERIALIZABLE, rien n'empêche d'autres transactions de faire des INSERTS dans les tables qui influent sur le solde de coupons. Donc à la fin de ma transaction je peux faire un commit pensant que le solde est suffisant alors qu'il a été changé par une opération dans une autre transaction.
J'en reviens à mon problème de départ... .
Voilà où j'en suis pour le moment. J'imagine que les systèmes de réservation sont légions et qu'il y a donc des solutions éprouvées à ce problème de validité des données au moment de finaliser une opération basée sur d'autres données de la BDD qui peuvent changer (par INSERT, UPDATE, etc...)
Merci pour votre aide.
Partager