LOCK IN SHARE MODEを使用すると、2番目のスレッドが値を読み取ることができますが、実際の値は、クエリ(読み取りコミット)またはトランザクション(繰り返し可能読み取り)が開始される前(MySQLがマルチバージョニングを使用するため)の値になります。 2番目のトランザクションで確認する必要があります)は、分離レベルによって定義されます。したがって、読み取り時に最初のトランザクションがコミットされていない場合、古い値が読み取られます。
シナリオでは、更新のためにselectを使用してレコードをロックするトランザクションを1つ持つのが最適です。これは、レコードで機能し、コミット/ロールバック時に3番目のトランザクションでレコードのロックを解除するものです。
select for updateを使用した2番目のスレッドトランザクションは、最初のスレッドが完了するのを待ってから、実際の値を読み取り、他のトランザクションを続行しないことを決定しますが、レコードがロックされていることをユーザーに通知します。
デッドロックを回避するには、select for update
を実行していることを確認してください 一意のインデックスを使用します。
コード例:
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);