JPA悲观锁定尝试永不超时 [英] JPA Pessimistic Lock attempt never times out

查看:120
本文介绍了JPA悲观锁定尝试永不超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在JPA中使用Pessimistic锁定,通过Hibernate 3对Postgres数据库进行锁定。

下面是一个例子:




pre> EntityManagerFactory factory;

//(初始化工厂)

EntityManager em1 = factory.createEntityManager();
EntityManager em2 = factory.createEntityManager();

// em1获得锁

EntityTransaction transaction1 = em1.getTransaction();
transaction1.begin();
MyObject object1 = em1.find(MyObject.class,1,LockModeType.PESSIMISTIC_READ);

// em2尝试锁定

Map< String,Object> timeoutProperties = new HashMap< String,Object>();
timeoutProperties.put(javax.persistence.lock.timeout,5000);

EntityTransaction transaction2 = em2.getTransaction();
transaction2.begin();
MyObject object2 = em2.find(MyObject.class,1,LockModeType.PESSIMISTIC_READ,timeoutProperties);

//五秒钟后,我希望em2能够纾困,但它永远不会。

transaction1.rollback();
transaction2.rollback();

据我所知,em2应该尝试长达五秒钟(5000毫秒)然后应该抛出异常。代码会变得僵局。



如果我在两个不同的线程中运行这个线程,那么当thread1(em1)释放它时,我会看到thread2(带有em2)获取锁。所以锁定正在发生,只是永远不会超时。



我得到与PESSIMISTIC_WRITE相同的效果,以及任何超时值(2ms,0ms'NO WAIT')等。

我使用Hibernate 3.6.10 Final(最新的Hibernate 3版本)和Postgres jdbc驱动程序9.2-1003.jdbc4(最新的驱动程序)。我正在运行一个Postgres 8.4数据库。



我发现的所有文档都表明这应该起作用。任何想法?



谢谢,
Alastair

解决方案

Postgres SELECT for update语法只提供了一些选项,如果不能马上获得锁,请不要等待。请参阅postgres文档。


为防止操作等待其他事务处理为
commit,请使用NOWAIT选项。使用NOWAIT,如果所选行无法立即锁定
,则该报表将报告
错误,而不是等待。请注意,NOWAIT仅适用于行级锁 -
所需的ROW SHARE表级锁仍采用普通的
方式(请参阅第13章)。您可以首先使用带有NOWAIT选项的LOCK,
,如果您需要无需等待即可获取表级锁。

在使用postgres时,我发现任何超过0的值都会导致hibernate发出 SELECT FOR UPDATE ,但当超时值为0时,它会发出 SELECT FOR UPDATE NO WAIT


I'm trying to use Pessimistic locking in JPA, over Hibernate 3 against a Postgres Database. I can't get the lock to time out - it just seems to hang forever.

Here's an example:

EntityManagerFactory factory; 

// (initialise the factory )

EntityManager em1 = factory.createEntityManager();
EntityManager em2 = factory.createEntityManager();

// em1 gets a lock

EntityTransaction transaction1 = em1.getTransaction();
transaction1.begin();
MyObject object1 = em1.find( MyObject.class, 1, LockModeType.PESSIMISTIC_READ );

// em2 tries for a lock

Map<String,Object> timeoutProperties = new HashMap<String,Object>();
timeoutProperties.put("javax.persistence.lock.timeout", 5000);

EntityTransaction transaction2 = em2.getTransaction();
transaction2.begin();
MyObject object2 = em2.find( MyObject.class, 1, LockModeType.PESSIMISTIC_READ, timeoutProperties );

// After five seconds I expect em2 to bail out, but it never does.

transaction1.rollback();
transaction2.rollback();

As I understand it, em2 should have tried for up to five seconds (5000ms) to get the lock and then should have thrown an exception. Instead the code becomes deadlocked.

If I run this in two different threads then I see that thread2 (with em2) gets the lock as soon as thread1 (em1) releases it. So the locking is happening, just never timing out.

I get the same effect with PESSIMISTIC_WRITE, and with any timeout value (2ms, 0ms 'NO WAIT') etc.

I'm using Hibernate 3.6.10 Final (the latest Hibernate 3 version) and Postgres jdbc driver 9.2-1003.jdbc4 (the latest driver). I'm running against a Postgres 8.4 database.

All the documentation I've found suggests this should work. Any ideas?

thanks, Alastair

解决方案

Postgres SELECT for update syntax only provides the options to not wait if a lock can not be obtained right away. See postgres docs.

To prevent the operation from waiting for other transactions to commit, use the NOWAIT option. With NOWAIT, the statement reports an error, rather than waiting, if a selected row cannot be locked immediately. Note that NOWAIT applies only to the row-level lock(s) — the required ROW SHARE table-level lock is still taken in the ordinary way (see Chapter 13). You can use LOCK with the NOWAIT option first, if you need to acquire the table-level lock without waiting.

When working with postgres I have observed that any value over 0 for the timeout will cause hibernate to issue SELECT FOR UPDATE but when timeout is 0 it will issue SELECT FOR UPDATE NO WAIT

这篇关于JPA悲观锁定尝试永不超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆