Conformément à la documentation MySql, MySql prend en charge le verrouillage à granularité multiple (MGL).
Terminal 1 ouvert:
// connecté à mysql
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select id, status from tracking_number limit 5 for update;
+----+--------+
| id | status |
+----+--------+
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| 5 | 0 |
+----+--------+
5 rows in set (0.00 sec)
mysql>
laissé ouvert et ouvert terminal-2:
// connecté à mysql
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select id, status from tracking_number limit 5 for update;
<!-- Hangs here. and after some time it says-->
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
Bien qu'il y ait beaucoup de lignes à récupérer, T2 attend la fin de t1.
Terminal 1 gauche tel quel, maintenant terminal 2:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
<!-- case 2.1 -->
mysql> select id, status from tracking_number where id=1;
+----+--------+
| id | status |
+----+--------+
| 1 | 0 |
+----+--------+
1 row in set (0.00 sec)
mysql> select id, status from tracking_number where id=2;
+----+--------+
| id | status |
+----+--------+
| 2 | 0 |
+----+--------+
1 row in set (0.00 sec)
<!-- case 2.2 -->
mysql> select * from tracking_number where id=2 for update;
<!-- Hangs here. and after some time -->
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
Mais pourquoi dans le cas 1, T2 attend le même ensemble de lignes que T1 a verrouillé?
Est-ce à dire que la requête de sélection illimitée (même avec le paramètre limint. J'ai également essayé avec une plage différente) bloque la table entière?
Ouverture d'un terminal et d'une transaction:
mysql> update tracking_number set status=4 where status=0 limit 5;
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5 Changed: 5 Warnings: 0
Laissé là et ouvert un autre terminal et transaction:
mysql> update tracking_number set status=5 where status=0 limit 5;
T2 n'a pas réussi jusqu'à ce que j'engage (ou annule) T1.
Permettez-moi de passer en revue vos cas et d'expliquer comment ces verrous fonctionnent:
1 cas
T1 souhaite mettre à jour certaines lignes de votre table de test. Cette transaction place le verrou IX sur toutes les tables et le verrou X sur les 5 premières lignes.
T2 souhaite mettre à jour certaines lignes de votre table de test. Cette transaction met IX (car IX compatible avec IX) sur toutes les tables et essaie de 5 premières lignes mais elle ne peut pas le faire car X n'est pas compatible avec X
Nous allons donc bien.
cas 2.1
T1 souhaite mettre à jour certaines lignes de votre table de test. Cette transaction a mis le verrou IX sur toutes les tables et le verrou X sur les 5 premières lignes.
T2 souhaite sélectionner certaines lignes de votre table de test. Et il ne place aucun verrou (car InnoDB fournit des lectures non verrouillables)
cas 2.1
T1 souhaite mettre à jour certaines lignes de votre table de test. Cette transaction a mis le verrou IX sur toutes les tables et le verrou X sur les 5 premières lignes.
T2 veut mettre à jour (sélectionner pour mettre à jour) certaines lignes de votre table de test. Placez IS sur toute la table et essaie d'obtenir le verrou S sur la ligne et échoue car X et S ne sont pas compatibles.
Soyez toujours conscient du niveau d'isolement: un niveau différent provoque un mécanisme différent pour libérer/acquérir des verrous
J'espère que ça aide