web-dev-qa-db-fra.com

Comportement de «sélection pour la mise à jour» de MySQL

Conformément à la documentation MySql, MySql prend en charge le verrouillage à granularité multiple (MGL).

cas 1

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.

cas-2

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
  1. Mais pourquoi dans le cas 1, T2 attend le même ensemble de lignes que T1 a verrouillé?

  2. 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?

  3. Existe-t-il un moyen de laisser les transactions se verrouiller indépendamment sans spécifier le champ de l'enregistrement (c'est-à-dire sans utiliser où champ = valeur)?
  4. Généralement (ou selon Java verrouillage simultané), le verrouillage d'écriture est exclusif et la lecture ne l'est pas. Dans le cas 2.1, bien que les enregistrements soient en mode de verrouillage d'écriture, comment T2 peut-il lire les mêmes enregistrements? cela est permis quel est l'intérêt de le verrouiller?
  5. Le cas 2.2 est compris.

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.

  1. Pourquoi ce comportement?
28
Pragalathan M

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

23
ravnur