7

Postgres データベースに対して Hibernate 3 を介して、JPA で悲観的ロックを使用しようとしています。ロックをタイムアウトにできません - 永遠にハングしているようです。

次に例を示します。

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();

私が理解しているように、em2 はロックを取得するために最大 5 秒間 (5000 ミリ秒) 試行し、その後例外をスローする必要がありました。代わりに、コードはデッドロックになります。

これを 2 つの異なるスレッドで実行すると、スレッド 1 (em1) が解放するとすぐにスレッド 2 (em2 を使用) がロックを取得することがわかります。そのため、ロックが発生していますが、タイムアウトすることはありません。

PESSIMISTIC_WRITE や任意のタイムアウト値 (2ms、0ms 'NO WAIT') などでも同じ効果が得られます。

Hibernate 3.6.10 Final (最新の Hibernate 3 バージョン) と Postgres jdbc ドライバー 9.2-1003.jdbc4 (最新のドライバー) を使用しています。Postgres 8.4 データベースに対して実行しています。

私が見つけたすべてのドキュメントは、これが機能することを示唆しています。何か案は?

ありがとう、アラステア

4

3 に答える 3

9

Postgres SELECT for update 構文は、ロックをすぐに取得できない場合に待機しないオプションのみを提供します。postgres のドキュメントを参照してください。

操作が他のトランザクションのコミットを待たないようにするには、NOWAIT オプションを使用します。NOWAIT を使用すると、選択した行をすぐにロックできない場合、ステートメントは待機するのではなく、エラーを報告します。NOWAIT は行レベルのロックにのみ適用されることに注意してください — 必要な ROW SHARE テーブルレベルのロックは通常の方法で取得されます (第 13 章を参照)。待機せずにテーブル レベルのロックを取得する必要がある場合は、最初に NOWAIT オプションを指定して LOCK を使用できます。

postgres を使用しているときに、タイムアウトの値が 0 を超えると休止状態が発生することがわかりましたSELECT FOR UPDATEが、タイムアウトが 0の場合は発生しますSELECT FOR UPDATE NO WAIT

于 2013-11-08T03:06:42.577 に答える
0

これをpersistence.xmlに入れます:

<property name="javax.persistence.lock.timeout" value="0"/>

または、最初のロックを呼び出す前にプロパティを設定します。

于 2013-10-30T17:21:20.040 に答える