【问题标题】:Spring JPA @QueryHint ignored for lock timeout?Spring JPA @QueryHint 因锁定超时而被忽略?
【发布时间】:2019-04-03 16:53:15
【问题描述】:

我在 Spring 数据 JpaRepository 中有一个查询,如下所示:

@Lock(value = LockModeType.PESSIMISTIC_WRITE)
@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "70000")})
Collection<AnyCLass> findBy ...

但是,在我的测试中,如果我在两个并发线程中运行事务(使用此查询作为第一个查询),我会在一秒钟后获得 SQL 锁定超时 (SQL Error: 50200, SQLState: HYT00),这是 H2 的默认设置在记忆中。 如果事务更快,那么一秒钟一切都会按预期进行。

【问题讨论】:

    标签: concurrency spring-data-jpa locking


    【解决方案1】:

    此问题的可能解决方法是对封闭方法进行简单的重试:

    @Retryable(backoff = @Backoff(value = 500,random = true))
    void getSometingLocked(){
     findById(id)
    }
    

    【讨论】:

    • 谢谢。这就是我们已经在做的事情。问题更多是关于提示被忽略的事实。然而,这对许多数据库来说是正常行为。
    • @PeMa 您能否详细说明这是“默认行为”?我正在使用 PostgreSQL,并在 Spring Data 中遇到了这个问题。但是,直接使用 EntityManager 可以按预期工作。
    • @H.Schulz 我不确定,“直接使用实体管理器”到底是什么意思。如果您配置实体管理器,您可能已经配置了另一个锁定超时。一般来说,事实证明,大多数数据库都忽略了查询提示。他们宁愿尊重在连接字符串中设置的标志。在没有设置任何标志的情况下,H2(用于测试的默认内存数据库)有 2 秒的锁定超时,而 MariaDB 有 30 秒(如果我没记错的话)。我不了解 PostgreSQL,但在测试中使用 H2 和在生产中使用 PostgreSQL 时,您可能会有不同的行为。
    • @PeMa 我的意思是使用entityManager.createQuery().setLockMode(PESSIMISTIC_FORCE_INCREMENT).setHint("javax.persistence.lock.timeout", 25000).getSingleResult() 会在没有nowait 选项的情况下使用select for update,并使用问题中的spring-data-jpa 存储库会使用nowait,即忽略查询提示。
    • @H.Schulz 好吧,在这种情况下,这听起来像是 springs JPA 实现中的一个错误。也许你可以在那里提出错误报告。 jira.spring.io/projects/DATAJPA/issues/…
    猜你喜欢
    • 2011-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-06
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    相关资源
    最近更新 更多