首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Hibernate JPA - PESSIMISTIC.WRITE不工作

Hibernate JPA - PESSIMISTIC.WRITE不工作
EN

Stack Overflow用户
提问于 2013-10-03 06:19:30
回答 2查看 3.4K关注 0票数 0

我正在使用JPA2.0的Hibernate实现在表行中创建一个计数器。我使用的是带有InnoDB引擎的MySQL 5.5。我正在尝试锁定计数器行,以便在我的代码递增计数器之前,JVM外部的任何进程都无法查看该计数器。我的代码如下所示:

代码语言:javascript
复制
  //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客户端登录到数据库并检查属性的值。该会话如下所示:

代码语言:javascript
复制
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连接可以在另一个事务运行时查看数据?

EN

回答 2

Stack Overflow用户

发布于 2013-10-07 02:18:57

默认的InnoDB隔离级别是REPEATABLE READ,它允许没有独占锁的事务读取(但不是更新)锁定的记录。这允许其他事务在记录上执行非脏读取。SERIALIZABLE似乎阻止对锁定记录的任何读取。您可以在使用hibernate.connection.isolation设置hibernate连接属性时设置隔离级别,尽管这会影响所有连接,这不是我愿意付出的代价。这篇SO post指出了一种针对每个连接执行此操作的方法,但该方法需要过时的方法:JPA and MySQL transaction isolation level

我最后用了其中一个

代码语言:javascript
复制
UPDATE counter SET value = LAST_INSERT_ID(value + 1);
SELECT LAST_INSERT_ID();

这里引用的方法:http://tedyoung.me/2011/04/14/jpa-counters-and-sequences/,它不需要任何锁定。

票数 1
EN

Stack Overflow用户

发布于 2021-03-04 03:44:24

对于select查询,这不起作用

如果您查询'select for update‘,那么您的查询将一直等到您的应用程序不释放锁

代码语言:javascript
复制
select * from property where property_key = 'DEPLOY_COUNTER' for update;

上面的查询将等待,直到锁被释放。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19147761

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档