Cet article vous présentera comment utiliser PDO pour effectuer des transactions en PHP. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il sera utile à tout le monde.
Concernant la question des transactions, nous n'en expliquerons pas davantage. Nous en apprendrons davantage lorsque nous étudierons le contenu lié à MySQL à l'avenir. Aujourd'hui, nous faisons principalement quelques petits tests sur les transactions opérationnelles en AOP, et nous pourrons peut-être trouver du contenu intéressant.
Tout d'abord, je crois que quiconque a acquis un peu de connaissances liées à MySQL sait que les deux types de tables couramment utilisés dans MySQL sont InnoDB et MyISAM. Bien sûr, nous ne parlerons pas de toutes leurs différences aujourd'hui, mais une différence est la plus évidente : MyISAM ne prend pas en charge les transactions. Alors, que se passe-t-il si nous effectuons des opérations de transaction sur MyISAM dans le cadre d'une opération PDO ?
// myisam try { $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->beginTransaction(); $pdo->exec("insert into tran_myisam (name, age) values ('Joe', 12)"); $pdo->exec("insert into tran_myisam2 (name, age) values ('Joe', 12, 33)"); // sleep(30); $pdo->commit(); } catch (Exception $e) { $pdo->rollBack(); echo "Failed: " . $e->getMessage(), PHP_EOL; }
Les tables tran_myisam et tran_myisam2 sont toutes deux des tables de type MyISAM. Dans ce code, nous avons délibérément écrit la mauvaise instruction d'insertion de tran_myisam2 et l'avons laissée aller au catch. Le résultat réel de l'exécution est que le message d'erreur est affiché normalement et que les données de la table tran_myisam sont également insérées. En d'autres termes, les opérations de transaction sur les tables MyISAM n'ont aucun effet. Bien sûr, PDO ne signalera pas activement les erreurs. Si nous faisons de la deuxième instruction SQL une instruction normale, PDO se terminera normalement sans aucune erreur ni invite.
// innodb try { $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->beginTransaction(); $pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)"); $pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12, 3)"); // sleep(30); $pdo->commit(); } catch (Exception $e) { $pdo->rollBack(); echo "Failed: " . $e->getMessage(), PHP_EOL; }
Nous pouvons activer le commentaire de la ligne de code sleep(30);, ce qui signifie faire une pause de 30 secondes avant la validation de la transaction, puis afficher la table infomation_schema.INNODB_TRX dans MySQL. Ce qui est montré dans ce tableau est la transaction en cours d'exécution. Lorsque la table de type InnoDB est exécutée, vous pouvez voir un enregistrement de la transaction en cours d'exécution, mais vous ne verrez aucune information dans la table de type MyISAM.
Supposons que nous oubliions d'écrire commit() et qu'aucune erreur ne soit signalée, cette instruction sera-t-elle exécutée avec succès ? Tout comme le code ci-dessous.
try { $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->beginTransaction(); $pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)"); $pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12)"); // 忘记写 $pdo->commit(); 了 } catch (Exception $e) { $pdo->rollBack(); echo "Failed: " . $e->getMessage(), PHP_EOL; }
PHP annulera cette transaction après la fin de l'exécution du script, c'est-à-dire lorsque l'objet $pdo est détruit. En d’autres termes, l’instruction SQL ici ne sera pas exécutée. Cependant, essayez de ne pas le faire, car dans un environnement formel, notre code est très complexe et risque de ne pas être détruit avec succès. Dans ce cas, certaines transactions peuvent prendre beaucoup de temps. Le résultat final est que l'IPQS de MySQL sera extrêmement élevé, et il est difficile d'en trouver la raison. Par conséquent, lorsque nous utilisons des transactions, nous devons nous rappeler que commit() et rollBack() sont nos frères et ne doivent pas être laissés pour compte.
De même, nous continuerons à étendre en fonction de la question précédente. Si deux transactions sont exécutées séquentiellement et que la première transaction n’est pas validée ou annulée, la transaction suivante peut-elle quand même être exécutée ?
// innodb try { $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->beginTransaction(); $pdo->exec("insert into tran_innodb (name, age) values ('Joe', 12)"); $pdo->exec("insert into tran_innodb2 (name, age) values ('Joe', 12)"); // 忘记写 $pdo->commit(); 了 } catch (Exception $e) { $pdo->rollBack(); echo "Failed: " . $e->getMessage(), PHP_EOL; } // innodb try { $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->beginTransaction(); $pdo->exec("insert into tran_innodb (name, age) values ('BW', 12)"); $pdo->exec("insert into tran_innodb2 (name, age) values ('BW', 12)"); // sleep(30); $pdo->commit(); } catch (Exception $e) { $pdo->rollBack(); echo "Failed: " . $e->getMessage(), PHP_EOL; // Failed: There is already an active transaction }
On peut voir que la deuxième transaction rapporte directement une erreur, le contenu est : "Il y a une transaction active existante ici." Autrement dit, si la transaction précédente n’est pas validée ou annulée, la deuxième transaction ne peut pas être exécutée.
Aujourd'hui, nous venons d'apprendre et de tester quelques problèmes mineurs liés aux transactions, mais bien que les problèmes soient mineurs, ils peuvent provoquer de graves accidents en ligne. lors du développement. Nous étudierons les détails des transactions lorsque nous étudierons MySQL en profondeur à l'avenir.
Code de test :
https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/PHP中使用PDO操作事务的一些小测试.php
Apprentissage recommandé : Tutoriel vidéo php
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!