首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在postgres - Hibernate中设置锁定超时

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

Stack Overflow用户
提问于 2018-08-15 00:21:35
回答 4查看 7.6K关注 0票数 13

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

代码语言:javascript
复制
entityManager.createQuery("SELECT value from Table where id=:id")
            .setParameter("id", "123")
            .setLockMode(LockModeType.PESSIMISTIC_WRITE)
            .setHint("javax.persistence.lock.timeout", 10000)
            .getSingleResult();

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

但是,不管超时设置如何,线程都会挂起,直到另一个线程完成。

看看这个例子:

代码语言:javascript
复制
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();
});

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

Hibernate以这种方式生成我对数据库的请求:

代码语言:javascript
复制
SELECT value from Table where id=123 FOR UPDATE

在这个answer中,我看到Postgres只允许将超时设置为0的SELECT FOR UPDATE NO WAIT,但不能以这种方式设置超时。

有没有其他方法可以和Hibernate / JPA一起使用?也许以某种方式推荐了this way

EN

回答 4

Stack Overflow用户

发布于 2018-08-17 19:36:20

Hibernate支持bunch of query hints。您正在使用的锁为查询设置超时,而不是为悲观锁设置超时。查询和锁是相互独立的,您需要使用下面显示的提示。

但在此之前,请注意,Hibernate本身并不处理超时。它只将它发送到数据库,并且它依赖于数据库,如果它应用它,以及如何应用它。

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

代码语言:javascript
复制
entityManager.createQuery("SELECT value from Table where id=:id")
        .setParameter("id", "123")
        .setLockMode(LockModeType.PESSIMISTIC_WRITE)
        .setHint("javax.persistence.lock.timeout", 10000)
        .getSingleResult();
票数 6
EN

Stack Overflow用户

发布于 2018-08-15 18:27:37

我觉得你可以试试

代码语言:javascript
复制
SET LOCAL lock_timeout = '10s';
SELECT ....;

我怀疑Hibernate是否支持这种开箱即用的方式。你可以试着找一种方法来扩展它,但不确定它是否值得。因为我认为在postges数据库(即mvcc)上使用锁不是最明智的选择。

您还可以在代码中执行NO WAIT和延迟重试多次。

票数 2
EN

Stack Overflow用户

发布于 2018-08-15 04:32:27

有一个lock_timeout参数,它可以执行您想要的操作。

您可以按用户或按数据库在postgresql.conf中或使用ALTER ROLEALTER DATABASE设置它。

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

https://stackoverflow.com/questions/51845853

复制
相关文章

相似问题

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