乐观锁定和可伸缩性

Optimistic locking and scalibility

我想知道 optimistic locking mechanism 在 Hibernate 中的用途是什么。所以,我读过这里

https://vladmihalcea.com/preventing-lost-updates-in-long-conversations/关于这样的场景:

1. Alice requests a certain product for being displayed
2. The product is fetched from the database and returned to the browser
3. Alice requests a product modification
4. The product must be updated and saved to the database

而且,确实在这种情况下使用乐观锁定似乎是合理的。

但是,托管或分离的实体被跟踪/保存在持久性上下文中。 Persistence Context 仅限于内存进程。是不是说最多只有一个服务实例就可以使用?

乐观锁定的基本假设是您不会并行编辑同一条记录。这意味着我们不执行任何显式锁定或同步。我们加载数据,然后执行写操作。如果另一个事务已写入同一条记录,则写入操作将失败。但是,它独立于服务实例的数量。事实上,应用程序可以使用乐观锁定和任意数量的服务实例运行良好。

考虑以下示例。一旦你有一个实体,你有一个 属性 注释 @Version 如下...

@Entity
@Table(name="test_entity")
    public class TestEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false, unique = true)
    private Long id;
    @Column(name = "value", nullable = true)
    private String value;
    @Version
    @Column(nullable = false)
    private Integer version;

    ... getters & setters

}

然后是代码:

session.saveOrUpdate(testEntity);
session.flush();

将生成以下查询...

update
    test_entity 
set
    value=?,
    version=? 
where
    id=? 
    and version=?

如果通过同一服务实例或单独实例中的并行事务更改了版本,则 hibernate 将注意到更新不会影响数据库中的任何行,因为 ID 匹配,但版本有已通过不同的交易更改。

只要是这种情况(session.update(...) 方法影响 0 行),hibernate 将抛出一个运行时异常以指示乐观锁失败 - OptimisticLockException。这意味着主要考虑因素是您是否相信您的用户会同时更新同一条记录。

但是,如果您正在使用二级缓存并希望将其与乐观锁定结合使用,则需要确保您使用的是正确配置的分布式缓存。否则 second-level-cache 意味着您将从 second-level-cache (而不是从持久性上下文)而不是从数据库加载实例。在没有分布式缓存的情况下,您的 second-level-cache 当然不会知道不同的服务实例更新了记录,从而导致版本增加。然后当你去更新数据库中的记录时(使用上面的查询)你更新 0 条记录并得到一个 OptimisticLockException。