Est-il possible de sélectionner/afficher tous les verrous actuels qui ont été supprimés à l'aide de la fonction GET_LOCK
?
Notez que les verrous GET_LOCK
sont différents des verrous de table, comme ceux obtenus avec LOCK TABLES
- les lecteurs qui veulent savoir comment voir ces verrous doivent lire Détection des tables verrouillées (verrouillé par LOCK TABLE)
À partir de MySQL 5.7, le schéma de performances expose tous les verrous de métadonnées, y compris les verrous liés à la fonction GET_LOCK()
.
Voir http://dev.mysql.com/doc/refman/5.7/fr/metadata-locks-table.html
SHOW FULL PROCESSLIST;
Vous verrez les serrures à l'intérieur
À partir de MySQL 5.7, c'est possible, mais il faut d'abord activer l'instrument mdl
dans la table performance_schema.setup_instruments
. Vous pouvez le faire temporairement (jusqu'au prochain redémarrage du serveur) en exécutant:
UPDATE performance_schema.setup_instruments
SET enabled = 'YES'
WHERE name = 'wait/lock/metadata/sql/mdl';
Ou de manière permanente, en ajoutant l'incantation suivante à la section [mysqld]
de votre fichier my.cnf
(ou à tout autre fichier de configuration lu par MySQL lors de votre installation):
[mysqld]
performance_schema_instrument = 'wait/lock/metadata/sql/mdl=ON'
(Naturellement, MySQL devra être redémarré pour que le changement de configuration prenne effet si vous adoptez cette dernière approche.)
Les verrous que vous retirez après que l'instrument mdl
a été activé sont visibles en exécutant un SELECT
sur la table performance_schema.metadata_locks
. Comme indiqué dans la documentation, les serrures GET_LOCK
ont un OBJECT_TYPE
de 'USER LEVEL LOCK'
, afin que nous puissions filtrer notre requête avec une clause WHERE
:
mysql> SELECT GET_LOCK('foobarbaz', -1);
+---------------------------+
| GET_LOCK('foobarbaz', -1) |
+---------------------------+
| 1 |
+---------------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM performance_schema.metadata_locks
-> WHERE OBJECT_TYPE='USER LEVEL LOCK'
-> \G
*************************** 1. row ***************************
OBJECT_TYPE: USER LEVEL LOCK
OBJECT_SCHEMA: NULL
OBJECT_NAME: foobarbaz
OBJECT_INSTANCE_BEGIN: 139872119610944
LOCK_TYPE: EXCLUSIVE
LOCK_DURATION: EXPLICIT
LOCK_STATUS: GRANTED
SOURCE: item_func.cc:5482
OWNER_THREAD_ID: 35
OWNER_EVENT_ID: 3
1 row in set (0.00 sec)
mysql>
La signification des colonnes dans ce résultat est généralement documentée de manière adéquate à l'adresse suivante: https://dev.mysql.com/doc/refman/fr/metadata-locks-table.html , mais il convient de noter un point de confusion: la colonne OWNER_THREAD_ID
ne contient pas l'ID connection (comme cela serait montré dans la PROCESSLIST
ou retourné par CONNECTION_ID()
) du thread qui détient le verrou. De manière confuse, le terme "ID de thread" est parfois utilisé comme synonyme de "ID de connexion" dans la documentation MySQL, mais c'est pas une de ces fois. Si vous voulez déterminer l'ID connection de la connexion qui détient un verrou (par exemple, pour supprimer cette connexion avec KILL
), vous devez rechercher le PROCESSLIST_ID
qui correspond au THREAD_ID
dans la table performance_schema.threads
. Par exemple, pour tuer la connexion qui tenait mon verrou au-dessus ...
mysql> SELECT OWNER_THREAD_ID FROM performance_schema.metadata_locks
-> WHERE OBJECT_TYPE='USER LEVEL LOCK'
-> AND OBJECT_NAME='foobarbaz';
+-----------------+
| OWNER_THREAD_ID |
+-----------------+
| 35 |
+-----------------+
1 row in set (0.00 sec)
mysql> SELECT PROCESSLIST_ID FROM performance_schema.threads
-> WHERE THREAD_ID=35;
+----------------+
| PROCESSLIST_ID |
+----------------+
| 10 |
+----------------+
1 row in set (0.00 sec)
mysql> KILL 10;
Query OK, 0 rows affected (0.00 sec)
Si vous voulez simplement déterminer si un verrou nommé particulier est actuellement maintenu, vous pouvez utiliser IS_USED_LOCK
:
SELECT IS_USED_LOCK('foobar');
Si une connexion détient le verrou, l'ID de cette connexion sera renvoyé; sinon, le résultat est NULL
.
J'ai trouvé le moyen suivant qui peut être utilisé si vous savez le nom du verrou
select IS_USED_LOCK('lockname');
cependant, je n'ai trouvé aucune information sur la façon de lister tous les noms.
Un autre moyen simple consiste à utiliser:
mysqladmin debug
Cela vide beaucoup d’informations (y compris les verrous) dans le journal des erreurs.
Vous pouvez également utiliser ce script pour trouver le verrou dans MySQL.
SELECT
pl.id
,pl.user
,pl.state
,it.trx_id
,it.trx_mysql_thread_id
,it.trx_query AS query
,it.trx_id AS blocking_trx_id
,it.trx_mysql_thread_id AS blocking_thread
,it.trx_query AS blocking_query
FROM information_schema.processlist AS pl
INNER JOIN information_schema.innodb_trx AS it
ON pl.id = it.trx_mysql_thread_id
INNER JOIN information_schema.innodb_lock_waits AS ilw
ON it.trx_id = ilw.requesting_trx_id
AND it.trx_id = ilw.blocking_trx_id