JeuWeb - Crée ton jeu par navigateur
[Résolu] Soucis avec les transactions - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : [Résolu] Soucis avec les transactions (/showthread.php?tid=7812)



[Résolu] Soucis avec les transactions - MeTaLLiQuE - 26-05-2017

Hello !

Je reviens vers vous pour un soucis au niveau des transactions...

J'ai mon code pour valider le déplacement de mes troupes, j'utilise les transactions pour vérifier l'intégralité du code (qu'aucun soucis n'a eu lieu en route).

Voici le schéma du code :

Il y avait un soucis dans mon code, qui a fait l'utilisation du rollback (qu s'est bien exécutée) mais... une des requêtes s'est quand même effectuée malgré le rollback... (la ligne est  toujours insérée dans la bdd...)


try
{
$bdd->beginTransaction();

      Tout mon code ici, requêtes, vérifications, etc...

    $bdd->commit();
}

catch(Exception $e)
{
    $bdd->rollBack();
}

J'ai manqué quelqu'un chose ou bien ?

Je ne sais pas si j'ai été assez explicite... Désolé d'avance ^^

Merci :')


RE: Soucis avec les transactions - Xenos - 26-05-2017

Salut,
certaines requêtes commitent les transactions, principalement celles qui altèrent ou créent des tables. Donc, tu as peut-être un "commit" caché de ce genre quelque part (il faudrait que tu fournisses la liste des queries executées, ie: le mysql query log). Egalement, si tu passes par une couche intermédiaire autre que PDO, celle-ci a peut-être des règles spécifiques qui "commitent" la transaction. Si tu passes directement par PDO, vérifie les paramètres de ton driver et vérifie qu'il n'y a pas deux transactions qui s'imbriquent (mysql ne gérant pas les transactions imbriqués, un "START TRANSACTION" commitera la précédente, ie: c'est une requête SQL qui fait un "commit chaché").
Enfin, vérifie tout bêtement que cette ligne insérée n'est pas juste hors de la transaction Smile

(Nota: je suppose que le "span" est une erreur? Car mettre le formattage HTML au milieu de la transaction SQL, je trouve cela vaseux: la transaction est inutilement bloquée pendant le formattage, parfois lent, et elle sera rollback si le formattage a foiré, ce qui n'est pas forcément l'effet désiré)


RE: Soucis avec les transactions - MeTaLLiQuE - 26-05-2017

Je vais vérifier et je vous tiens au courant !

Non, je ne passe pas par une couche intermédiaire.

Pour le span, je l'ai juste mis ici à titre indicatif, il n'y a pas de ça dans mon code Big Grin

EDIT : En faite, je lance le beginTransaction, en-dessous je mets une requête de type INSERT (c'est celle-ci qui est exécutée).

Merci Smile


RE: Soucis avec les transactions - Ter Rowan - 26-05-2017

sinon, mets le vrai code (vire ce qui n'est pas bdd) ce sera plus simple que de tirer dans le vide


RE: Soucis avec les transactions - MeTaLLiQuE - 26-05-2017

Hello, 


// ON LANCE LA TRANSACTION
$bdd->beginTransaction();

// On insère l'id action
$reqInsertAction = $bdd->prepare("INSERT INTO actions VALUES (:id_user, :id_cible, 'deplacement', :duree)");
$reqInsertAction->bindValue(':id_user', $_SESSION['id'], PDO::PARAM_INT);
$reqInsertAction->bindValue(':id_cible', $_POST['joueur'], PDO::PARAM_INT);
$reqInsertAction->bindValue(':duree', TEMPS_DEPLACEMENT, PDO::PARAM_INT);
$reqInsertAction->execute();

// On récupère l'id de l'action
$id_action = $bdd->lastInsertId();

Je fais ensuite des vérifications dans le code et si une vérification a échouée ou réussie :


if(!$isError)
{
    // Message de validation

    // SI TOUT EST OK ON LANCE LE COMMIT
    $bdd->commit();
}
else
{
    // SI PRESENCE D'UNE ERREUR, ON ANNULE TOUT !
    $bdd->rollback();

    // Message d'erreur
}

Le tout enrobé d'un try et catch

Je ne sais pas si ça peut vous aider ou pas :/

Merci :)


RE: Soucis avec les transactions - Xenos - 26-05-2017

Citation :une des requêtes [n'est pas rollback]

J'en déduis donc qu'il y a plusieurs requêtes, contrairement à ce qu'on voit ici, donc ce n'est toujours pas le code global D'autant que là, je trouve que cela sent mauvais: tu try/catch avec un rollback dans le catch et un autre rollback dans le try "if tout s'est bien passé"? c'est pas l'usage correct d'un try/catch: le but du try/catch est de sortir ert d'insoler le flux des erreurs. Tu devrais avoir juste un "commit" en fin de "try", car tout s'est nécessairement bien passé si le try arrive à son terme, et un rollback dans le catch car si on tombe dans le catch, c'est qu'un truc a foiré (et donc, tu rollback).

D'où aussi ce que je te demandais, qui évitera encore mieux les tirs dans le vide: ouvre le ton mysql query log, et donne les requêtes qui sont exécutées sur ta page. On y verra plus clair vis-à-vis de ce que la BDD reçoit. Là, je pense simplement que la BDD reçoit le START TRANSACTION, puis le INSERT, puis le COMMIT puis l'intérieur de ton "if" doit throw un truc qui remonte dans le catch et tente de ROLLBACK alors qu'aucune transaction n'est ouverte.

Nota: perso, c'est pour cela que j'aime le fait de placer sa logique SQL et métier dans une procédure par page: je trouve que cela évite ce genre de méandres et cela structure bien proprement les choses (en échange, je reconnais que cela peut être très chiant de déboguer un procédure stockée tant les outils pour cela n'existent toujours pas, malgré des décennies de bons et loyaux service de la part du SQL).


RE: Soucis avec les transactions - MeTaLLiQuE - 27-05-2017

Yop,

Vais plus m'expliquer...

Je n'ai pas affiché les autres requêtes car tout se déroule bien pour elles...

En faite, je lance le START TRANSACTION, puis j'insère dans la bdd une ligne dans la table "actions" me permettant de récupérer un identifiant unique pour pouvoir retracer l'action du joueur.
Au fil du script, je lance diverses vérification et s'il y a une erreur, j'annule tout. Pour éviter de devoir tout supprimer (les lignes insérées etc...) je "biaise" un peu l'utilisation de ces transactions, en lançant une rollback (au lieu de lancer la commit).

MYSQL LOG
Citation :69 Query START TRANSACTION
69 Query INSERT INTO actions (`id_user`,`id_cible`,`type`,`duree`) VALUES (1, '3', 'deplacement', 1495852777)
69 Query SELECT s.id,COUNT(p.id) AS nbSoldat FROM soldats AS s
LEFT JOIN population AS p ON p.id_soldat=s.id_soldat
WHERE s.id_soldat= 2 AND p.id_user= 1 AND p.categorie='soldat' AND p.localisation= '1' AND id_action IS NULL AND p.recrutement<= 1495841977
69 Query ROLLBACK
69 Quit



RE: Soucis avec les transactions - Xenos - 27-05-2017

Citation : Je n'ai pas affiché les autres requêtes car tout se déroule bien pour elles...
Oui, mais si l'une de ces requêtes génère un "commit" caché, alors on ne pourra pas t'aider vu qu'on ne les connaît pas.

Après, il se peut aussi tout simplement que ta table "actions" soit en MyISAM, qui ne gère pas les transactions.


RE: Soucis avec les transactions - MeTaLLiQuE - 27-05-2017

Ah... après vérification... il se trouve qu'en effet, que ma table était en MyISAM... --'

Je pouvais toujours chercher l'erreur dans mon code ^^

Merci pour ton aide Smile