Mysql
 sql >> Base de données >  >> RDS >> Mysql

FOR UPDATE v/s LOCK IN SHARE MODE :Autoriser les threads simultanés à lire la valeur d'état mise à jour de la ligne verrouillée

LOCK IN SHARE MODE permettra au 2ème thread de lire la valeur, mais la valeur réelle sera celle avant la requête (lecture validée) ou avant le démarrage de la transaction (lecture répétable) (puisque MySQL utilise le multi-versioning ; et ce que doivent être vus par la deuxième transaction est défini par le niveau d'isolement). Donc si la 1ère transaction n'est pas validée au moment de la lecture, l'ancienne valeur sera lue.

Dans votre scénario, il est préférable d'avoir 1 transaction qui verrouille l'enregistrement avec select pour la mise à jour, une autre qui fonctionne sur l'enregistrement et sur commit/rollback la troisième déverrouille l'enregistrement.

La deuxième transaction de thread avec select for update attendra la fin de la première, puis lira la valeur réelle et décidera de ne pas continuer avec les autres transactions, mais d'informer l'utilisateur que l'enregistrement est verrouillé.

Pour éviter les blocages, assurez-vous que vous effectuez la select for update en utilisant un index unique.

Exemple de code :

connection.setautocommit(false);
//transaction-1
PreparedStatement ps1 = "Select locked from tableName for update where id="key" and   locked=false);
ps1.executeQuery();

//transaction 2
PreparedStatement ps2 = "Update tableName set locked=true where id="key";
ps2.executeUpdate();
connection.setautocommit(true); // here we allow other transactions / threads to see the new value

connection.setautocommit(false);
//transaction 3
PreparedStatement ps3 = "Update tableName set aField="Sthg" where id="key" And date="D" and topic="T";
ps3.executeUpdate();

// probably more queries

// reset locked to false
 PreparedStatement ps4 = "Update tableName set locked=false where id="key";
ps4.executeUpdate();

//commit
connection.setautocommit(true);