Hibernate JPA - PESSIMISTIC.WRITE 不工作
Posted
技术标签:
【中文标题】Hibernate JPA - PESSIMISTIC.WRITE 不工作【英文标题】:Hibernate JPA - PESSIMISTIC.WRITE not working 【发布时间】:2013-10-02 22:19:29 【问题描述】:我正在使用 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 连接可以在另一个事务正在运行时查看数据?
【问题讨论】:
【参考方案1】:默认的 InnoDB 隔离级别是 REPEATABLE READ,它允许没有排他锁的事务读取(但不更新)锁定的记录。这允许其他事务对记录进行非脏读。 SERIALIZABLE 似乎可以防止对锁定记录的任何读取。您可以在使用hibernate.connection.isolation 设置休眠连接属性时设置隔离级别,尽管这会影响所有连接,而不是我愿意支付的成本。这篇 SO 帖子指出了一种按连接执行此操作的方法,但该方法需要不推荐使用的方法: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/,不需要任何锁定。
【讨论】:
【参考方案2】:对于选择查询,这不起作用
如果您查询“选择更新”,它将起作用 那么您的查询将等到您的应用程序不释放锁定的时间
select * from property where property_key = 'DEPLOY_COUNTER' for update;
上面的查询会一直等到锁被释放。
【讨论】:
以上是关于Hibernate JPA - PESSIMISTIC.WRITE 不工作的主要内容,如果未能解决你的问题,请参考以下文章
spring.jpa.hibernate.hbm2ddl 和 spring.jpa.hibernate.ddl 之间的区别
Spring Hibernate JPA 联表查询 复杂查询