normalement c'est le role de l'isolation des transactions ce genre de bazar, inutile de réinventer la roue. Tu demande à ton connecteur un niveau d'isolation (typiquement dans ton cas, l'isolation SERIALIZABLE) et tu fais tout comme un grand dans UNE SEULE transaction . En cas d'accès concurrent, si quelqu'un modifie les même données que toi ou des données sur lequelles tu aurait pu te baser, la deuxième personne à sauver aura une erreur lors du commit (à cause de l'isolation) et ses changements ne seront pas effectués. Exemple avec deux utilisateurs qui sont sur les même critère dans deux cas typique:
A: début de transaction
A: récupère la ligne 5 (valeur A) et l'affiche à l'écran
B: début de transaction
B: récupère les lignes 5 (valeur A),6 (valeur B) et 7 (valeur C) et les affiche à l'écran
B: efface les lignes 5 et 6, et change la ligne 7 (valeur C2) (par exemple, 3 demandes de process industriel regroupées par un opérateur en une seule dans la ligne 7)
A: modifie la ligne 5 (valeur A2) (par exemple, changement des spécifications demandées par le client)
A: sauve (commit) -> ok
B: sauve (commit)-> erreur, rollback, changements annulé
B: nouvel affichage
B: récupère les lignes 5 (valeur A2),6 (valeur B) et 7 (valeur C)
B: efface la ligne 6 et change la 7 (valeur C2) (seulement deux process à réunir au final)
B: sauve (commit) -> ok
A: début de transaction
A: récupère la ligne 5 (valeur A) et l'affiche à l'écran
B: début de transaction
B: récupère les lignes 5 (valeur A),6 (valeur B) et 7 (valeur C) et les affiche à l'écran
B: efface les lignes 5 et 6, et change la ligne 7 (valeur C2) (par exemple, 3 demandes de process industriel regroupées par un opérateur en une seule dans la ligne 7)
A: modifie la ligne 5 (valeur A2) (par exemple, changement des spécifications demandées par le client)
B: sauve (commit) -> ok
A: sauve (commit)-> erreur, rollback, changements annulé
A: nouvel affichage
B: récupère la ligne 5 (n'existe plus)
B: "désolé monsieur, vos trois commandes sont déjà envoyées en production, je ne peux plus les changer"
B: rien à sauver (rollback) -> ok
Il faut bien sur être rigoureux dans ton code et ne faire entrer dans ta transaction aucune information qui proviendrais d'une requête faite dans une transaction précédente. Les select for update ne sont pas nécessaire dans ce cas (sous oracle en tout cas), puisque c'est au moment du commit que le SGDB va voir que, dans ta transaction, tu a lu des données qui depuis ont changé, ce qui rend impossible de garantir les contraintes du "SERIALIZABLE".
Partager