LOCK IN SHARE MODE pozwoli drugiemu wątkowi na odczytanie wartości, ale rzeczywista wartość będzie tą przed zapytaniem (odczyt zatwierdzony) lub przed rozpoczęciem transakcji (odczyt powtarzalny) (ponieważ MySQL używa wielu wersji; i co muszą być widziane przez drugą transakcję jest określona przez poziom izolacji). Jeśli więc pierwsza transakcja nie zostanie zatwierdzona w momencie odczytu, odczytana zostanie stara wartość.
W twoim scenariuszu najlepiej mieć 1 transakcję, która blokuje rekord z opcją wyboru do aktualizacji, inna niż działa na rekordzie i przy zatwierdzeniu/przywróceniu, trzecia odblokowuje rekord.
Transakcja drugiego wątku z opcją wyboru aktualizacji poczeka na zakończenie pierwszej, a następnie odczyta rzeczywistą wartość i zdecyduje się nie kontynuować innych transakcji, ale poinformuje użytkownika, że rekord jest zablokowany.
Aby uniknąć impasu, upewnij się, że wykonujesz select for update
używając unikalnego indeksu.
Przykładowy kod:
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);