JPA 2.0 の Hibernate 実装を使用して、テーブル行にカウンターを作成しています。InnoDB エンジンで MySQL 5.5 を使用しています。コードがインクリメントするまで、JVM の外部のプロセスがそのカウンターを表示できないように、カウンター行をロックしようとしています。私のコードは次のようになります。
//inside a Transaction....
//key is an enum
final PropertyKey key = PropertyKey.DEPLOY_COUNTER;
final Query query =
entityManager.createQuery("FROM Property s where propertyKey = :key").setParameter("key", key);
query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
LOG.debug("Blocking (maybe) while waiting to update deploy counter");
final Property counterAsProperty = (Property) query.getSingleResult();
try
{
Thread.sleep(15000);
//while sleeping I use MySQL cli to check value of property in database
}
catch (InterruptedException e)
{
e.printStackTrace();
}
//in java, increment counter by one and then save in db
//...
Thread.sleep() を使用して、トランザクションの途中でコードを一時停止します。スレッドがスリープしている間に、MySQL CLI クライアントを使用してデータベースにログインし、プロパティの値を確認します。そのセッションは次のようになります。
user@mypc [user]> begin work;
Query OK, 0 rows affected (0.00 sec)
user@mypc [user]> select * from property where property_key = 'DEPLOY_COUNTER';
+----+---------+-----------+--------------------+----------------+
| id | version | encrypted | property_key | property_value |
+----+---------+-----------+--------------------+----------------+
| 10 | 0 | 0 | DEPLOY_COUNTER | 66 |
+----+---------+-----------+--------------------+----------------+
スレッドがスリープを終了してトランザクションが完了するまでブロックすると予想していたときに、クエリがすぐに (0.00 秒) 返されることに注意してください。LockModeType.PESSIMISTIC_WRITE についての私の理解は、取得した行を排他ロックに入れて、別のトランザクションによる読み取りまたは書き込みができないということです。
注: スレッドがスリープしている間、この行への更新はブロックされます。
PESSIMISTIC_WRITE ロック モードを設定した場合、他のトランザクションが実行されているときに別の DB 接続がデータを表示できるのはなぜですか?