Maison > Article > développement back-end > Une brève analyse du fonctionnement simple du mécanisme de verrouillage MySQL par PHP
Mécanisme de verrouillage
Verrouillage partagé et verrouillage exclusif
Verrouillage partagé (verrouillage en lecture) : les autres transactions peuvent lire, mais ne peuvent pas écrire.
Verrouillage exclusif (verrouillage en écriture) : les autres transactions ne peuvent ni lire ni écrire.
Pour MySQL, il existe trois niveaux de verrouillage : niveau page, niveau table, niveau ligne
- Le moteur représentatif typique du niveau page est BDB.
- Un moteur typique au niveau des lignes est INNODB.
- Les moteurs représentatifs typiques au niveau de la table sont MyISAM, MEMORY et l'ISAM d'il y a longtemps.
- Le moteur de stockage BDB utilise le verrouillage au niveau de la page, mais prend également en charge les verrous au niveau de la table
- Le moteur de stockage InnoDB prend en charge à la fois le verrouillage au niveau de la ligne (verrouillage au niveau de la ligne) et le verrouillage au niveau de la table. des verrous au niveau de la ligne, mais les verrous au niveau de la ligne sont utilisés par défaut.
- Les moteurs de stockage MyISAM et MEMORY utilisent des verrous au niveau des tables
Recommandations d'apprentissage gratuites associées : programmation php(vidéo)
Mode de verrouillage au niveau de la table MyISAM :
Méthode de verrouillage de la table MyISAM :
- Verrouillage en lecture partagé de la table (Table Read Lock) : Non Il bloquera les demandes de lecture des autres utilisateurs sur la même table, mais il bloquera les demandes d'écriture sur la même table
- Verrouillage d'écriture de la table : il bloquera les opérations de lecture et d'écriture des autres utilisateurs sur la même table ; 🎜>
Utilisez la commande LOCK TABLE pour verrouiller explicitement la table MyISAM
- LOCK TABLES real_table (READ|WRITE), insert_table ( READ|WRITE); //Lock
- UNLOCK TABLES; //Unlock
Exemple :Opération 1.1PHPPar exemple, il y a un compte (id, nom ,cash), héros (numéro, nom, pays) ces deux tables
verrouiller les tables compte lu ; Ajouter un compte comme verrou en lecture seule
- Requête de processus actuelle : sélectionner * à partir du héros ; La table de rapport 'hero' n'a pas été verrouillée avec LOCK TABLES.
Le processus actuel modifie les autres tables : mettre à jour le nom du jeu de héros = "ss" où numéro = 1 ; signalera que la table 'héros" n'a pas été verrouillée avec LOCK TABLES
Le processus actuel modifie le nom de la table : mettre à jour le nom du jeu de comptes = "ssss" où id=1 ; il signalera que la table 'compte' a été verrouillée avec un verrou READ et ne peut pas être mise à jour
Si un autre processus MySQL arrive, vous pouvez interroger d'autres tables et comptes, mais vous ne pouvez pas modifier le compte, et vous continuerez d'attendre et devrez être libéré. Le verrou est exécuté
<?php/** * Created by PhpStorm. * User: Administrator * Date: 2021/4/29 0029 * Time: 11:20 */$link = new mysqli('127.0.0.1', 'root', '123', 'db_school'); // 连接数据库if(mysqli_connect_errno()){ // 检查连接错误 printf("连接失败:%s<br>", mysqli_connect_error()); exit();}//(s1)$table = "account";$type = "read";$sql1 = "LOCK TABLES $table $type";$link->query($sql1);//处理逻辑//$sql1 = "select * from $table;"; //(s1)true//$sql1 = "select * from hero;"; //false//$sql1 = "update hero set name='ss' where number=1; "; //false$sql1 = "update account set name='ssss' where id=1;"; //false$result = $link->query($sql1);var_dump($result);sleep(20); //测试 //假设还没释放锁,开启cmd进mysql(s2)可以查询,但不能执行更改和删除操作,会等待这边释放锁$link->query("unlock tables"); //取消全部的锁//解锁后正常操作//$result = $link -> query($sql1);//var_dump($result);$link->close();
Confliction de verrouillage au niveau de la table de requête2. Méthode de verrouillage InnoDB :afficher le statut comme 'Table%';
Table_locks_immediate fait référence au nombre de fois où des verrous au niveau de la table peuvent être obtenus immédiatement
- Table_locks_waited fait référence au nombre de fois où des verrous au niveau de la table les verrous ne peuvent pas être obtenus immédiatement et doivent attendre
Pour les instructions SELECT ordinaires, InnoDB n'ajoutera aucun verrou Le verrouillage ne peut être utilisé que pendant l'exécution de la transactionLes verrous ne peuvent être utilisés que pendant l'exécution de la transaction. Ils ne seront libérés que lorsque la validation ou la restauration sera exécutée, et tous les verrous seront libérés en même temps.
Verrou(s) partagé(s) : SELECT * FROM nom_table OÙ… VERROUILLER EN MODE PARTAGE. D'autres sessions peuvent toujours interroger l'enregistrement et ajouter des verrous partagés en mode partage à l'enregistrement. Cependant, si la transaction en cours doit mettre à jour l'enregistrement, cela risque de provoquer un blocage. Tout le monde peut le lire, mais il ne peut pas le modifier. Il ne peut être modifié que lorsque l'un des verrous partagés exclusifs est verrouilléOpération PHP 2.1
- Verrou exclusif (X) : SELECT * FROM table_name WHERE ... FOR UPDATE ; Les autres sessions peuvent interroger l'enregistrement, mais ne peuvent pas ajouter de verrous partagés ou exclusifs à l'enregistrement, mais attendent d'obtenir le verrou. Je veux le changer, mais vous ne pouvez pas le changer ni le lire
#select … verrouiller en mode partage //Verrouillage partagé- #select … pour la mise à jour //Verrouillage exclusif
##Dans MySQL 8.0
Verrou partagé (S) : SELECT * FROM nom_table WHERE … FOR SHARE- Verrou exclusif (X) : SELECT * FROM nom_table WHERE … FOR UPDATE[NOWAIT|SKIP LOCKED]
– NOWAIT : Découverte Après avoir attendu un verrou, une erreur sera immédiatement renvoyée. Il n'est pas nécessaire d'attendre que le verrou expire et signale une erreur.- –SKIP LOCKED : ignorez les lignes verrouillées et mettez directement à jour les autres lignes, mais veillez à ce que les résultats de la mise à jour ne répondent pas aux attentes.
<?php/** * Created by PhpStorm. * User: Administrator * Date: 2021/4/29 0029 * Time: 10:06 */$link = new mysqli('127.0.0.1', 'root', '123', 'db_school'); // 连接数据库if(mysqli_connect_errno()){ // 检查连接错误 printf("连接失败:%s<br>", mysqli_connect_error()); exit();}//案例1$id = 1; //明确指定主键,并且有此数据,row lock (行锁)//$id = -1; //明确指定主键,若查无此数据,无lock (无锁)$link->autocommit(0); // 开始事务(s1)//FOR UPDATE仅适用于InnoDB,且必须在交易区块(BEGIN/COMMIT)中才能生效。$sql = "select * from account where id=$id for update";$link->query($sql);/*** * 此时其他mysql进程可以查询该记录,但是不能对该记录加共享锁或排他锁,而是等待获得锁。 *///(s1)可以进行更改,和查询等操作//$sql1 = "update account set name='aaa' where id=$id;"; //进行更改//$sql1 = "select * from account where id=$id;"; //进行查询$sql1 = "delete from account where id=$id;"; //进行删除$result = $link -> query($sql1);var_dump($result);sleep(20); //测试 //假设还在事务处理中,开启cmd进mysql(s2)执行更改和删除操作,会等待这边释放锁$link->commit();$link->close();Afficher les tables verrouillées
afficher les TABLES OUVERTES où In_use > en cours d'exécution.
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!