sql - Hibernate 如何在提交事务之前对乐观锁进行行版本检查

标签 sql hibernate race-condition optimistic-locking pessimistic-locking

在提交当前事务之前,hibernate 检查行的版本时,应该发出 sql select用于获取行的语句。

假设在发出 select 之后语句 hibernate 发现行版本没有改变,因此它应该继续提交事务。

我想知道 hibernate 如何确保在选择行和提交当前事务之间的时间段内没有任何其他事务会更新行更改其版本号? hibernate 可以做的唯一可能的事情似乎是使用 Select ... For Update 进行悲观锁定的行版本选择。或者具有这种隔离级别的事务将锁定正在读取的行。

如果我的想法是真的:

  • 那么 hibernate 乐观锁实际上确实对其操作使用了悲观锁,尽管悲观锁被持有的时间很短,因为事务将在此之后立即提交。
  • 否则我们在行版本检查和提交之间有一个很短的时间段,可能会发生竞争条件。

  • 请分享您的想法。

    最佳答案

    对于默认的乐观锁机制,由 @Version 给出的机制。注释,没有这种风险。
    乐观锁定不需要任何额外的 SELECT 来获取和检查实体修改后的版本。因此,涉及两个步骤:

  • 从数据库中获取实体及其版本:
     SELECT * FROM PRODUCT WHERE ID = 1;
    
  • UPDATE 或 DELETE 将使用由获取实体的同一个 SELECT 获取的版本:
     UPDATE PRODUCT SET (LIKES, QUANTITY, VERSION) = (5, 10, 3) 
     WHERE ID = 1 AND VERSION = 2;
    

  • 因此,Hibernate 不会检查实体版本。 DB 使用 WHERE 子句对其进行检查。
    Hibernate 只检查 updateCount PreparedStatement.executeUpdate 的结果方法调用。如果计数不是 updateCount ,这意味着该行已被删除或版本已更改,这意味着我们正在使用陈旧数据,因此 OptimisticLockException将被抛出。
    因此,默认值 @Version 不会发生冲突。基于乐观锁,因为一条记录一次只能被一个事务修改,一旦行被修改锁定,锁将一直保持到事务提交或回滚。
    只有显式 LockModeType.OPTIMISTIC 可能导致竞争条件。但是,您可以轻松地fix that using a pessimistic shared or explicit lock .

    关于sql - Hibernate 如何在提交事务之前对乐观锁进行行版本检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52988292/

    相关文章:

    MYSQL根据3列去除重复行

    sql - Postgres 文本列比较错误

    java - Hibernate逆="true"在级联="all"时保存父级保存子级

    hibernate - Grails 3-使用条件在字符串列表中查找字符串

    go - Go HTTP 处理程序中的简单竞争条件 - 这真的是竞争条件吗?

    sql - 如何在 sql server 2016 中更改 JSON 列名

    sql - 我如何在这里使用 SQL If 语句?

    java - Controller 在进行 spring/hibernate 调用时会阻塞吗?

    c++ - 使用锁定文件作为多个进程之间的锁定的正确方法

    python - scipy.weave.inline 的竞争条件