Contrôle de modification de la base de donnée (Mysql)

boubavic2
Invité n'ayant pas de compte PHPfrance

08 juil. 2005, 10:42

Salut a tous,

J'ai un petit soucis.

Voila le topo :
J'utilise PEAR:DB_DataObject pour manipuler ma base de donnée. Il arrive souvent que j'insere de nombreuses données a la suite qui depende les unes des autres. Mais le probleme c'est que parfois il semble que des insertions echouent (je n'en connais pas la cause) ce qui fait que certaines donnée sont inserées et d'autre non... du coup les données ne sont plus du tout cohérente...

Voila j'aimerai savoir comment faire donc pour outre passer cela ?

J'ai bien penser au mode transactionnel mais je ne crois pas que ce soit compatible avec PEAR.

A un moment je pensai faire boucler une insertion tant qu'elle n'etait pas reussite mais cette solution est loin d'etre viable dans la mesure où si la base de donnée est inaccessible à ce moment la, il y aura une boucle infini qui tournerait sur Apache ... bref je ne sais pas trop comment m'y prendre.

Merci

Eléphant du PHP | 413 Messages

08 juil. 2005, 11:48

bonjour,

premierement, est-ce que grace au code retour de la commande insert, tu peux savoir si ça a marché ou pas ? si tu peux savoir ça, c'est dejà pas mal. en cas d'echec, tu peux réessayer l'insertion, ou interrompre le traitement... à toi de voir.

deuxiemement, si tu as besoin de transactions, et que PEAR:DB_DataObject ne supporte pas cette fonctionnalité, alors je te conseille de te tourner vers un autre outil qui les supporte.
--
Goeb

boubavic2
Invité n'ayant pas de compte PHPfrance

08 juil. 2005, 12:07

lors d'un insert, la fonction retourne l'identifitiant d'insertion.

Mais le probleme est le suivant :
Si je fais :

Code : Tout sélectionner

A->insert() B->insert() C->insert() D->insert()
Chaque insert etant dependant les uns des autres. Si par exemple l'insert foire pour l'objet C. J'aurai alors fait les insert pour les objets A et B...Que faire alors ?

Cet exemple ne comporte que 4 objets, mais dans la pratique je peux avoir a faire succeder une 10zaine - 15zaine d'action...

Modérateur PHPfrance
Modérateur PHPfrance | 6037 Messages

08 juil. 2005, 12:09

Modération : et zouuu ! Déplacement dans Base de données

Eléphant du PHP | 91 Messages

08 juil. 2005, 14:33

Typiquement ce probléme est géré par les transactions.

Transaction

1/ Tu ouvres une transaction => START TRANSACTION
2/ A chaque insertion tu testes le code retour.
3/ Si code retour KO => ROLLBACK
4/ Si tous les codes retour des insertions sont OK => COMMIT

ROLLBACK annule toutes les insertions depuis START TRANSACTION, y compris celles qui sont passées
COMMIT valide toutes les insertions depuis START TRANSACTION, sauf celles qui ne sont pas passées

Si PEAR:DB_DataObject n'a pas de méthode pour gérer les transaction , rien de doit t'empêcher d'utiliser une méthode ExecStatement pour lancer "START TRANSACTION". Même chose pour COMMIT ou ROLLBACK.

PS : vérifier version MySQL, les premiéres version de MySQL ne gére pas les transactions à ma connaissance.
PS2 : les intertions peuvent ce faire dans différentes tables.

Eléphant du PHP | 181 Messages

07 oct. 2005, 10:49

bonjour,

moi j'ai + ou - le meme probleme....

je dois confimrer l'insertion de ma base avec un bouton confirmer et utiliser la commande commit....

mais comment utiliser la commande START TRANSACTION???

comment utilise ton cette commande en php???

j'ai essaye ca mais ca ne marche pas:
$sql_tmp = "START TRANSACTION;insert into temp(produit_id, quantite, session) values('".$produit_id."', '".$quantite."', '".$session."');";
	$req_tmp = mysql_query($sql_tmp) or die('Erreur SQL !<br>'.$sql_tmp.'<br>'.mysql_error());
merci de votre aide.... :wink:

Eléphant du PHP | 91 Messages

07 oct. 2005, 15:27

Un peu de théorie, définition d’une transaction : Séquence d'instructions SQL qui définit une unité de travail logique. Une transaction est traitée dans son intégralité ou pas du tout. La transaction se termine soit par une instruction COMMIT, qui rend TOUTES les modifications apportées aux données permanentes, soit par une instruction ROLLBACK, qui annule TOUTES les modifications effectuées pendant la transaction.

Concrétement

Dans une session (c’est à dire une connexion; une transaction est propre à une connexion. Si l’utilisateur A ouvre une transaction, l’utilisateur B ne pourra pas la terminer pour lui.) tu créé une transaction. Ensuite tu envoies des ordres SQL. Puis tu termines avec l’instruction COMMIT pour tout valider ou ROLLBACK pour tou annuler.
$req_tmp = mysql_query(‘START TRANSACTION;’);
// Test $req_tmp si ok
$req_tmp = mysql_query(‘INSERT ….’);
// Test $req_tmp si ok
$req_tmp = mysql_query(‘INSERT ….’);
// Test $req_tmp si ok
$req_tmp = mysql_query(‘INSERT ….’);
// Test $req_tmp si ok
// si tout est OK
mysql_query(‘COMMIT’);
// si un KO
mysql_query(‘ROLLBACK’);
Exemple concret
Lors d’un virement d’un compte A vers un compte B. Il faut que les deux ordres soit validé ensemble ou annulé ensemble. Il ne faut pas qu’un seul ordre sur les deux soit passé et pas l’autre (sinon toi ou ton banquier rallerez)
$req_tmp = mysql_query(‘START TRANSACTION;’);
// Test $req_tmp si ok
$req_tmp = mysql_query(‘UPDATE compte set mt=mt-100 WHERE id_compte=’A’; ’);
// Test $req_tmp si ok
$req_tmp = mysql_query(‘UPDATE compte set mt=mt+100 WHERE id_compte=’B’; ’);
// Test $req_tmp si ok
// si tout est OK
mysql_query(‘COMMIT’);
// si un KO
mysql_query(‘ROLLBACK’);
En éspérant que cela éclaire un peu ta lanterne

Eléphant du PHP | 181 Messages

07 oct. 2005, 15:45

oui merci bcp pour l'explication et pour le code php....

je sais pas si en fait je suis bien parti dans mon raisonnement...

j'ai poste ca sur php car en fait ma question etait liee... --> http://www.phpfrance.com/forums/voir_sujet-9333.php

tu en penses quoi toi??? je devrais utiliser quelle methode??

table temp, avec les commit et rollback ou alors les sessions???

la je sais pas du tout comment m'y prendre... chui un peu perdu a vrai dire

:oops:

merci d'avance

Eléphant du PHP | 91 Messages

07 oct. 2005, 16:10

Des remarques en vrac :

1/ (Sans lien direct avec ta question) Pour gérer une commande, il y a usuellement deux tables "commande" et "ligne_commande". "commande" contient code_commande + id_hotesse. "ligne_commande" contient id_commande (fk), id_produit et qte.

2/ Une commande qui est entrée en base (dans la table commande) doit l'être complétement (pas de demi commande ...)(d'ou utilisation des transactions)

3/ Lors de la saisie par l'hotesse de la commande, la commande ne doit pas être insérer dans la table "commande". Les informations sont conservés dans un cookie ou table temporaire. Si crash, l'hotesse peut (avec un peu de chance) reprendre une parti de sa commande ou recommencer. Mais il n'y a pas de "demi commande" en base. Ta base reste intégre d'un point de vue fonctionnel.

4/ Une fois la saisie de la commande terminé. L'hotesse clique sur un bouton ENREGISTRER. A ce moment tu ouvres une transaction, tu inséres toutes tes lignes dans la table commande, si tout est ok commit, si probléme rollback.