如何在postgres中设置锁定超时 - Hibernate

Dan*_*aub 9 java postgresql hibernate jpa

我正在尝试为Lock我正在处理的行设置一个直到下次提交:

entityManager.createQuery("SELECT value from Table where id=:id")
            .setParameter("id", "123")
            .setLockMode(LockModeType.PESSIMISTIC_WRITE)
            .setHint("javax.persistence.lock.timeout", 10000)
            .getSingleResult();
Run Code Online (Sandbox Code Playgroud)

我认为应该发生的是,如果两个线程同时尝试写入数据库,一个线程将在另一个线程之前到达更新操作,第二个线程应该等待10秒然后抛出PessimisticLockException.

但是,无论超时设置如何,线程都会挂起,直到另一个线程完成.

看看这个例子:

database.createTransaction(transaction -> {
    // Execute the first request to the db, and lock the table
    requestAndLock(transaction);

    // open another transaction, and execute the second request in
    // a different transaction
    database.createTransaction(secondTransaction -> {
        requestAndLock(secondTransaction);
    });

    transaction.commit();
});
Run Code Online (Sandbox Code Playgroud)

我预计在第二个请求中,事务将等到超时设置然后抛出PessimisticLockException,但它会永远死锁.

Hibernate以这种方式向db生成我的请求:

SELECT value from Table where id=123 FOR UPDATE
Run Code Online (Sandbox Code Playgroud)

在这个答案中我看到Postgres只允许SELECT FOR UPDATE NO WAIT将超时设置为0,但是不可能以这种方式设置超时.

还有其他方法可供我使用Hibernate / JPA吗?也许以某种方式推荐这种方式

Tho*_*sen 5

Hibernate 支持一堆查询提示。您正在使用的那个设置查询的超时,而不是悲观锁。查询和锁是相互独立的,需要用到下图的提示。

但在您这样做之前,请注意,Hibernate 本身不会处理超时。它只将它发送到数据库,它取决于数据库,是否以及如何应用它。

要为悲观锁设置超时,您需要改用javax.persistence.lock.timeout提示。下面是一个例子:

entityManager.createQuery("SELECT value from Table where id=:id")
        .setParameter("id", "123")
        .setLockMode(LockModeType.PESSIMISTIC_WRITE)
        .setHint("javax.persistence.lock.timeout", 10000)
        .getSingleResult();
Run Code Online (Sandbox Code Playgroud)

  • 它不适用于 Postgres...如果为 javax.persistence.lock.timeout 提供 0 ... NO_WAIT 将触发,但使用其他值 postgres 会忽略它。 (3认同)

Lau*_*lbe 3

有一个lock_timeout参数可以完全满足您的要求。

您可以在每个用户或每个数据库中postgresql.conf或与每个用户或每个数据库一起设置它。ALTER ROLEALTER DATABASE