MySQL
MySQL LOCK TABLE
Recherche…
Syntaxe
LOCK TABLES nom_table [READ | ÉCRIRE]; // Lock Table
DÉVERROUILLEZ LES TABLES; // Déverrouiller les tables
Remarques
Le verrouillage est utilisé pour résoudre les problèmes de concurrence. Le verrouillage est requis uniquement lors de l'exécution d'une transaction, qui lit d'abord une valeur à partir d'une base de données et, plus tard, écrit cette valeur dans la base de données. Les verrous ne sont jamais requis pour les opérations d'insertion, de mise à jour ou de suppression autonomes.
Il existe deux types de serrures disponibles
READ LOCK - lorsqu'un utilisateur lit uniquement depuis une table.
WRITE LOCK - lorsqu'un utilisateur lit et écrit à la fois un tableau.
Lorsqu'un utilisateur détient un WRITE LOCK
sur une table, aucun autre utilisateur ne peut lire ou écrire sur cette table. Lorsqu'un utilisateur détient un READ LOCK
sur une table, d'autres utilisateurs peuvent également lire ou maintenir un READ LOCK
, mais aucun utilisateur ne peut écrire ou maintenir un WRITE LOCK
sur cette table.
Si le moteur de stockage par défaut est InnoDB, MySQL utilise automatiquement le verrouillage au niveau des lignes afin que plusieurs transactions puissent utiliser la même table simultanément pour la lecture et l'écriture, sans se faire mutuellement attendre.
Pour tous les moteurs de stockage autres qu'InnoDB, MySQL utilise le verrouillage de table.
Pour plus de détails sur le verrouillage de la table Voir ici
Mysql Serrures
Les verrous de table peuvent être un outil important pour ENGINE=MyISAM
, mais sont rarement utiles pour ENGINE=InnoDB
. Si vous êtes tenté d'utiliser des verrous de table avec InnoDB, vous devez repenser la façon dont vous travaillez avec les transactions.
MySQL permet aux sessions client d'acquérir explicitement des verrous de table dans le but de coopérer avec d'autres sessions pour accéder aux tables ou d'empêcher d'autres sessions de modifier des tables pendant les périodes où une session nécessite un accès exclusif à ces dernières. Une session peut acquérir ou libérer des verrous uniquement pour elle-même. Une session ne peut pas acquérir de verrous pour une autre session ou libérer des verrous détenus par une autre session.
Les verrous peuvent être utilisés pour émuler des transactions ou pour accélérer la mise à jour des tableaux. Ceci est expliqué plus en détail plus loin dans cette section.
Commande: LOCK TABLES table_name READ|WRITE;
vous ne pouvez affecter que le type de verrou à une seule table;
Exemple (READ LOCK):
LOCK TABLES table_name READ;
Exemple (WRITE LOCK):
LOCK TABLES table_name WRITE;
Pour voir que le verrou est appliqué ou non, utilisez la commande suivante
SHOW OPEN TABLES;
Pour vider / supprimer tous les verrous, utilisez la commande suivante:
UNLOCK TABLES;
EXEMPLE:
LOCK TABLES products WRITE:
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;
Par exemple, toute connexion externe ne peut écrire aucune donnée dans la table des produits avant de déverrouiller le produit de la table
EXEMPLE:
LOCK TABLES products READ:
INSERT INTO products(id,product_name) SELECT id,old_product_name FROM old_products;
UNLOCK TABLES;
Par exemple, toute connexion externe ne peut lire aucune donnée de la table des produits avant de déverrouiller le produit de la table
Verrouillage au niveau des lignes
Si les tables utilisent InnoDB, MySQL utilise automatiquement le verrouillage au niveau des lignes afin que plusieurs transactions puissent utiliser la même table simultanément pour la lecture et l'écriture, sans se faire mutuellement attendre.
Si deux transactions tentent de modifier la même ligne et que les deux utilisent le verrouillage au niveau des lignes, l'une des transactions attend que l'autre se termine.
Le verrouillage au niveau des lignes peut également être obtenu en utilisant l' SELECT ... FOR UPDATE
pour chaque ligne à modifier.
Considérons deux connexions pour expliquer le verrouillage au niveau des lignes en détail
Connexion 1
START TRANSACTION;
SELECT ledgerAmount FROM accDetails WHERE id = 1 FOR UPDATE;
Dans la connexion 1, le verrouillage de niveau de ligne est obtenu par l' SELECT ... FOR UPDATE
.
Connexion 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;
Lorsque quelqu'un essaie de mettre à jour la même ligne dans la connexion 2, cela attendra que la connexion 1 termine la transaction ou le message d'erreur sera affiché en fonction du paramètre innodb_lock_wait_timeout
, qui par défaut est 50 secondes.
Error Code: 1205. Lock wait timeout exceeded; try restarting transaction
Pour afficher les détails de ce verrou, exécutez SHOW ENGINE INNODB STATUS
---TRANSACTION 1973004, ACTIVE 7 sec updating
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 4, OS thread handle 0x7f996beac700, query id 30 localhost root update
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1
------- TRX HAS BEEN WAITING 7 SEC FOR THIS LOCK TO BE GRANTED:
Connexion 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 250 WHERE id=2;
1 row(s) affected
Mais lors de la mise à jour d'une autre ligne de la connexion 2 sera exécutée sans aucune erreur.
Connexion 1
UPDATE accDetails SET ledgerAmount = ledgerAmount + 750 WHERE id=1;
COMMIT;
1 row(s) affected
Maintenant, le verrouillage de ligne est libéré, car la transaction est validée dans la connexion 1.
Connexion 2
UPDATE accDetails SET ledgerAmount = ledgerAmount + 500 WHERE id=1;
1 row(s) affected
La mise à jour est exécutée sans aucune erreur dans la connexion 2 après le verrouillage de la ligne de la connexion 1 en terminant la transaction.