Mysql
 sql >> Database >  >> RDS >> Mysql

FOR UPDATE v/s LOCK IN SHARE MODE:Consenti ai thread simultanei di leggere il valore di stato aggiornato della riga bloccata

LOCK IN SHARE MODE consentirà al 2° thread di leggere il valore, ma il valore effettivo sarà quello prima dell'avvio della query (lettura confermata) o prima dell'avvio della transazione (lettura ripetibile) (poiché MySQL utilizza il multi-versione; e cosa devono essere visti dalla seconda transazione è definito dal livello di isolamento). Quindi, se la prima transazione non viene confermata al momento della lettura, verrà letto il vecchio valore.

Nel tuo scenario è meglio avere 1 transazione che blocca il record con seleziona per l'aggiornamento, un'altra che funziona sul record e su commit/rollback una terza sblocca il record.

La seconda transazione thread con select for update attenderà il completamento della prima, quindi leggerà il valore effettivo e deciderà di non continuare con le altre transazioni, ma di informare l'utente che il record è bloccato.

Per evitare deadlock, assicurati di eseguire select for update utilizzando un indice univoco.

Codice di esempio:

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);