Met LOCK IN SHARE MODE kan de 2e thread de waarde lezen, maar de werkelijke waarde zal de waarde zijn voordat de query (read commit) of voordat de transactie (repeatable read) is gestart (omdat MySQL multi-versioning gebruikt; en wat moeten worden gezien door de tweede transactie wordt bepaald door het isolatieniveau). Dus als de 1e transactie niet is vastgelegd op het moment van lezen, wordt de oude waarde gelezen.
In jouw scenario is het het beste om 1 transactie te hebben die het record vergrendelt met selecteren voor update, een andere dan werkt op het record en bij commit/rollback derde ontgrendelt het record.
De tweede threadtransactie met selecteren voor update wacht tot de eerste is voltooid, leest dan de werkelijke waarde en besluit om niet verder te gaan met de andere transacties, maar om de gebruiker te informeren dat het record is vergrendeld.
Om een impasse te voorkomen, moet u ervoor zorgen dat u de select for update
. uitvoert met behulp van een unieke index.
Voorbeeldcode:
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);