Nous n'expliquerons pas plus sur les transactions. Nous entrerons plus en profondeur lors de l'apprentissage de MySQL dans le. compréhension future. 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.
Que se passe-t-il lors de l'utilisation de transactions sur MyISAM ?
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.
Que se passera-t-il si la transaction n'est pas validée ou annulée ?
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.
La transaction précédente n'a pas été validée ou annulée. La prochaine transaction sera-t-elle exécutée ?
De même, nous continuerons à développer sur la base 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.
Résumé
Aujourd'hui, nous venons d'apprendre et de tester quelques problèmes mineurs liés aux transactions. Cependant, bien que les problèmes soient mineurs, ils peuvent provoquer de graves accidents en ligne. Tout le monde doit être prudent lors du développement. Nous étudierons les détails des transactions lorsque nous étudierons MySQL en profondeur à l'avenir.
测试代码: https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/PHP中使用PDO操作事务的一些小测试.php
Apprentissage recommandé : "Tutoriel vidéo PHP"