Cet article vous présente une introduction aux opérations atomiques et au verrouillage de fichiers en PHP (exemples de code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Opérations atomiques PHP, troupeau de verrouillage de fichiers, transactions de base de données
PHP n'hérite pas du verrou Unix supporté par le standard POSIX, mais encapsule uniquement un troupeau d'appel système Linux (le sémaphore peut également être utilisé comme une serrure). Il va de soi que le mécanisme de verrouillage peut également être utilisé, bien qu'il soit moins efficace.
Le script php s'exécute dans le conteneur fastcgi, et fastcgi est multi-processus, donc si le programme php accède à des ressources critiques, cela entraînera inévitablement des résultats de programme incorrects.
On estime que nous devrions également considérer la question des conteneurs fastcgi
Description du problème : les pirates ont utilisé des outils pour brosser notre backend
Il y aura des remboursements lors de l'annulation de commandes. Les pirates ont annulé des commandes simultanément, ce qui entraînera des remboursements. remboursements multiples
Si les demandes arrivent une par une, même si l'intervalle est de 100 millisecondes, il n'y aura aucun problème
Un processus de traitement PHP est le suivant : lire le drapeau de remboursement, constater qu'il n'y a pas de remboursement, remboursement, puis définissez l'indicateur de remboursement
Le problème est que plusieurs demandes arrivent en même temps et que les signes de remboursement lus ne sont pas tous remboursés, donc plusieurs demandes sont remboursées
Le même fichier php est demandé plusieurs fois à en même temps, en même temps
En utilisant PHP file lock flock, nous l'avons essayé mais cela n'a pas fonctionné, nous avons donc utilisé la file d'attente C++
Utilisé C++ pour écouter sur un port, recevoir directement les paquets HTTP, puis renvoyer les paquets au format HTTP, programme PHP j'utilise curl pour accéder à mon programme C.
Il équivaut à un appel à distance et peut être déployé sur d'autres serveurs pour la distribution
Souvent, nous ne considérons pas notre capacité parallèle du code PHP, surtout lorsque notre code PHP peut lire et écrire sur une certaine ressource. Mais cela ne signifie pas que toutes les opérations en PHP sont atomiques, transactionnelles et parallélisables. Étant donné que le script PHP s'exécute dans le conteneur fastcgi et que fastcgi est multi-processus, si le programme PHP accède à des ressources critiques, cela entraînera inévitablement des résultats de programme incorrects.
La solution au problème est d'utiliser un mécanisme de verrouillage. PHP n'hérite pas des verrous Unix supportés par le standard POSIX : comme les verrous d'enregistrement fcntl, les verrous de thread, etc., mais encapsule uniquement un appel système Linux flock (le sémaphore peut également être utilisé comme verrou), flock sous forme de flock ($fp,$type), Où $fp est le descripteur de fichier et $type est :
/* Lorsqu'un fichier est ouvert en lecture et en écriture, il est généralement nécessaire d'ajouter un mécanisme de verrouillage au fichier*/
1. Verrou partagé LOCK_SH :
Habituellement, un verrou partagé est requis lorsqu'un processus demande une opération de lecture à partir d'un fichier. Les verrous partagés peuvent prendre en charge les opérations de lecture entre n'importe quel processus. Si vous écrivez un fichier avec un verrou partagé, le processus se bloquera et entrera dans l'état SLEEP jusqu'à ce que le verrou partagé soit déverrouillé
2. >généralement un processus Ajoutez un verrou exclusif à l'opération d'écriture du fichier Une fois le verrou ajouté au fichier, tout autre processus sera bloqué lors de l'accès au fichier jusqu'à ce qu'il soit déverrouillé.
Déverrouiller le descripteur de fichier verrouillé
<?php $usrinfo = isset($_GET["usrinfo"])?$_GET["usrinfo"]:exit(1); $stinfo = isset($_GET["stinfo"])?$_GET["stinfo"]:exit(1); echo $stinfo; $pid = posix_getpid(); $fp = fopen(“usrinfo.txt”,”a+”); $num = rand(0,100000); flock($fp,LOCK_EX); fwrite($fp,”user:”.$usrinfo.” stinfo:”.$stinfo.”–”.$pid.”–”.$num.”\n”); fwrite($fp,”talking 1 — pid:$pid and num:$num\n”); flock($fp,LOCK_UN); fclose($fp);
Par exemple : supprimez plusieurs articles, mais l'un d'entre eux a été supprimé. Si une erreur se produit ici, comment annuler toute l'opération et localiser le message d'erreur ?
Les transactions de base de données garantissent l'atomicité mais ne peuvent pas localiser les messages d'erreur. Mais que devons-nous faire si nous rencontrons un scénario dans lequel les transactions ne peuvent pas être utilisées ?
Appliquez une logique pour garantir que chaque opération est enregistrée, que le succès ou l'échec soit enregistré. Si quelque chose ne va pas au milieu, vous pouvez annuler le succès. Généralement, notre suppression est une fausse suppression, c'est donc très simple. S'il est supprimé, les informations complètes doivent être enregistrées lors de l'enregistrement.
Utilisez PHP pour réaliser une opération atomique, mais PHP lui-même ne fournit pas de mécanisme de verrouillage de processus. Utilisez le mécanisme de verrouillage de fichier PHP pour simuler le verrouillage de processus via un fichier. Verrouiller pour réaliser le fonctionnement atomique.
$fp = fopen( LOCK_FILE_PATH, "r" ); if (!$fp) { echo "Failed to open the lock file!"; exit(1);//异常处理 } flock ( $fp, LOCK_EX );
flock ( $fp, LOCK_UN ); fclose ( $fp );
define("LOCK_FILE_PATH", "/tmp/lock"); if( !file_exists(LOCK_FILE_PATH) ){ $fp = fopen( LOCK_FILE_PATH, "w" ); fclose ( $fp ); } $fp = fopen( LOCK_FILE_PATH, "r" ); if (!$fp) { echo "Failed to open the lock file!"; exit(1);//异常处理 } flock ( $fp, LOCK_EX ); //此处添加原子操作代码 flock ( $fp, LOCK_UN ); fclose ( $fp );
La méthode courante pour les opérations atomiques consiste à implémenter la restauration des données. Il est assez simple d'utiliser PHP pour implémenter l'opération de restauration de la base de données :
1, établir une connexion à la base de données
2, mysql_query('BEGIN');
3, $SQL = "...";
mysql_query($SQL); Effectuer les opérations de base de données correspondantes
4, déterminer les conditions de restauration :
if(mysql_errno)
{
print mysql_error();
mysql_query('ROLLBACK'); Revenir en arrière si une erreur se produit
exit();
5, vous pouvez répéter les étapes 3 et 4 ci-dessus pour démarrer le processus. (D'autres opérations peuvent être ajoutées au milieu, ne se limitant pas aux mises à jour de la base de données, mais attention à ne pas laisser une transaction prendre trop de temps, car cela verrouillerait toutes les tables que vous utilisez, ce qui affecterait l'utilisation d'autres programmes)
Vous pouvez également le faire en plusieurs fois. Après une instruction de mise à jour SQL correcte, écrivez délibérément une instruction incorrecte pour voir si elle est annulée.
6, terminez l'opération de restauration
mysql_query('COMMIT'); Pouvoir arriver ici signifie que les opérations de base de données ci-dessus sont toutes correctes et sont officiellement soumises pour exécution
De plus, il existe d'autres moyens de mettre fin à l'opération de restauration en plus de la validation.
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!