我正在使用JPA2.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连接可以在另一个事务运行时查看数据?
发布于 2013-10-07 02:18:57
默认的InnoDB隔离级别是REPEATABLE READ,它允许没有独占锁的事务读取(但不是更新)锁定的记录。这允许其他事务在记录上执行非脏读取。SERIALIZABLE似乎阻止对锁定记录的任何读取。您可以在使用hibernate.connection.isolation设置hibernate连接属性时设置隔离级别,尽管这会影响所有连接,这不是我愿意付出的代价。这篇SO post指出了一种针对每个连接执行此操作的方法,但该方法需要过时的方法:JPA and MySQL transaction isolation level
我最后用了其中一个
UPDATE counter SET value = LAST_INSERT_ID(value + 1);
SELECT LAST_INSERT_ID();这里引用的方法:http://tedyoung.me/2011/04/14/jpa-counters-and-sequences/,它不需要任何锁定。
发布于 2021-03-04 03:44:24
对于select查询,这不起作用
如果您查询'select for update‘,那么您的查询将一直等到您的应用程序不释放锁
select * from property where property_key = 'DEPLOY_COUNTER' for update;上面的查询将等待,直到锁被释放。
https://stackoverflow.com/questions/19147761
复制相似问题