Multi modifications sur des tables et intégrité

Eléphant du PHP | 124 Messages

04 août 2006, 12:27

Bonjour,

J'ai plusieurs requêtes l'une après l'autre du type :

- Update table1 where ....
- Update table2 where
- delete machin From table1

Je voudrais être sur que l'ensemble des requettes ce font bien avant de faire la dernière requette delete, sinon annuler les opérations réalisés dans les updates.

Je ne sais pas si la chose est possible, merci d'avance.

Eléphant du PHP | 332 Messages

04 août 2006, 13:55

par défaut, le fonctionnement de PHP avec les bases de données est en autocommit. C'est à dire que les instructions sont immédiatement validées dès leur exécution et les valeurs immédiatement inscrites dans la base.

Toutefois, le fonctionnement normal d'une application qui modifie (update, insert ou delete) des valeurs dans une base de données est le suivant.

Code : Tout sélectionner

début de la transaction ordre(s) SQL insert, update ou delete récupération du message d'erreur si pas d'erreur commit --> validation de la transaction sinon rollback --> annulation de la transaction fin si
La validation de la transaction signifie que tous les valeurs modifiées par le ou les ordres SQL sont définitivement inscrites dans la base. L'annulation de la transaction signifie que les valeurs d'origine sont remises en place. C'est idéal pour des cas où plusieurs modifications dans des bases dépendent l'une de l'autre et que l'échec d'une d'entre elles doit tout annuler.

Dans ton cas, tu pourrais avoir plusieurs update ; s'il y a une erreur sur au moins l'un d'entre eux, tu fais un rollback et tout les update sont annulés. S'ils sont tous OK, tu fais ton delete.

PHP permet de passer en mode commit manuel avec un certain nombre de bases de données. Mais j'ai l'impression qu'avec MySQL, cela n'existe qu'avec PHP5.

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

04 août 2006, 15:43

Cela ne dépend pas à ma connaissance de PHP mais du SGBD. Depuis que MySQL gère les transactions, même avec PHP4 on peut très bien faire ce genre de choses qui marchent très bien :
mysql_query('BEGIN');
// ... mes requêtes ...
mysql_query('COMMIT');
Peut-être que je me trompe mais je n'ai pas souvenir d'être tombé sur un article parlant du contraire, je vais regarder un peu.

Edit : un commentaire sur la doc semble confirmer

Eléphant du PHP | 332 Messages

04 août 2006, 20:09

Effectivement, ça marche en PHP4, mais uniquement si les tables MySQL sont configurées en InnoDB alors que l'usage veut qu'elles le soient en MyISAM qui est quand même le mode natif, donc le plus efficace de MySQL. Mais pourquoi pas ? Il faut juste regarder si les restrictions décrites ici ne sont pas gênantes.

Quant à l'emploi, il est un peu moins simple que les ordres mysqli_commit ou ora_rollback ; mais effectivement, cela existe. Mais attention, mysqli_commit ne fonctionne pas avec des tables MyISAM non plus.

Edit : A condition également que InnoDB soit activé sur MySQL. Je viens de faire un essai de création de table InnoDB chez mon hébergeur OVH et la table est créée en MyIsam ... Le mode InnoDB est désactivé.

Eléphant du PHP | 124 Messages

04 août 2006, 21:00

Code : Tout sélectionner

début de la transaction ordre(s) SQL insert, update ou delete récupération du message d'erreur si pas d'erreur commit --> validation de la transaction sinon rollback --> annulation de la transaction fin si


Dans ton cas, tu pourrais avoir plusieurs update ; s'il y a une erreur sur au moins l'un d'entre eux, tu fais un rollback et tout les update sont annulés. S'ils sont tous OK, tu fais ton delete.
Je suis en MyISAM et ta technique m'interesse, mais je comprend pas bien.
Tu entend quoi par faire un Rollback ?

Eléphant du PHP | 332 Messages

07 août 2006, 09:29

Tu entend quoi par faire un Rollback ?
Lorsque tu fais des insert, des update ou des delete dans une base de données qui supporte les transactions, les données ajoutées, modifiées ou effacées ne sont pas directement inscrites dans la base de données, mais dans une zone tampon.
Tant que ces données ne sont pas explicitement validées, les autres utilisateurs de la base travaillent sur les données originales tandis que toi (et seulement toi) travaille sur les données modifiées.

A ton gré, tu peux valider les modifications en effectuant un ordre commit et donc les rendre visible pour tout le monde et définitivement inscrites dans la base ou les annuler (ordre rollback) et revenir aux données originales.

Mais cela n'est valable que dans les bases qui supportent les transactions. Malheureusement, les tables en MyISAM ne supportent pas ce mécanisme et chaque ordre insert, update ou delete est définitivement inscrit dans la base de données.
Tu dois donc déjà commercer par regarder si tu peux passer tes tables en InnoDB : le type de table est modifiable via phpMyAdmin.

Eléphant du PHP | 124 Messages

08 août 2006, 11:00

Je ne comprend pas que ce problème ne soit pas plus souvent soulevé. Car dans le cas de requettes multiples sur plusieurs tables qui dépendent de la bonne exécution des première requettes, l'ensemble de la base risque d'être complètement en bordel pour une simple requettes non réalisée.

J'ai déja eu le cas d'un serveur qui avait un comportement bizarre pendant une journée ou les requettes passait / Passait pas et je me suis retrouvé avec plusieurs tables en vracs avec des liaisons de table complètement fausse.

Il faut en déduire que les tables MyISAM ne sont pas adaptés à des sites qui demandent des requettes multiples ( donc une bonne partie des sites ) ?

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

08 août 2006, 11:08

Le type de table MyIsam n'est pas très adapté à des contraintes d'intégrité référentielle puisque ... il ne gere pas ces contraintes :oops:

Pour cela, il faut soit que tu utilises InnoDB, comme te le conseille Henri, soit que tu changes de SGBD ;). Je te conseille donc de te renseigner sur InnoDB :D
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

08 août 2006, 21:10

Note: j'ai splitté la discussion sur Oracle vers ce topic