【问题标题】:hibernate optimistic lock mechanismhibernate乐观锁机制
【发布时间】:2018-03-29 21:08:59
【问题描述】:

我对休眠乐观锁(专用版本方式)非常好奇,我检查了休眠源代码,它告诉它在当前事务提交之前检查版本,但是如果在查询版本列之后有另一个事务恰好提交DB(在很短的时间间隔内),那么当前事务认为没有变化,所以旧事务会被错误地替换。

EntityVerifyVersionProcess.java

@Override
    public void doBeforeTransactionCompletion(SessionImplementor session) {
        final EntityPersister persister = entry.getPersister();

        if ( !entry.isExistsInDatabase() ) {
            // HHH-9419: We cannot check for a version of an entry we ourselves deleted
            return;
        }

        final Object latestVersion = persister.getCurrentVersion( entry.getId(), session );
        if ( !entry.getVersion().equals( latestVersion ) ) {
            throw new OptimisticLockException(
                    object,
                    "Newer version [" + latestVersion +
                            "] of entity [" + MessageHelper.infoString( entry.getEntityName(), entry.getId() ) +
                            "] found in database"
            );
        }
    }

这种情况可能吗?

希望有数据库领域专家可以帮助我。

非常感谢。

【问题讨论】:

  • 这会使它损坏和无用。不是一个很好的广告“使用乐观锁定,它通常不会破坏您的数据!”。
  • hmmm,其实我不认为这是一个重复的问题,那个问题是关于乐观锁机制的,但我不是......
  • 你不是什么?这似乎正是你所说的,不,事情没有破裂的机会。如果乐观锁定失败,一个事务将被回滚。
  • hibernate 源代码使用 SQL "SELECT VERSION FROM xx" 方式来检查版本更改,而不是附加 "WHERE VERSION=?"子句做

标签: java database hibernate transactions optimistic-locking


【解决方案1】:

基于对代码的快速浏览,EntityVerifyVersionProcess 用于读取事务,因此不会涉及数据丢失。这只会检查事务提交时是否返回已经过时的数据。对于READ COMMITTED 事务,我想这个可能返回的数据会立即变得陈旧,但如果不深入细节就很难说。

另一方面,写入事务使用EntityIncrementVersionProcess,这是一种完全不同的野兽,不会出现竞争条件。

public void doBeforeTransactionCompletion(SessionImplementor session) {
    final EntityPersister persister = entry.getPersister();
    final Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), session );
    entry.forceLocked( object, nextVersion );
}

【讨论】:

  • so it(OptimisticLock) 使用“SELECT xxx FOR UPDATE”的方式来加锁,而不是一开始就锁定一个长事务的记录,这是有道理的,感谢您的帮助。
  • 没有没有。没有选择更新,这将 在事务期间锁定记录。只是内部工作不简单,问题中的代码不处理updates,只处理selects。如果您正在执行更新,那么还有其他 *Process 类涉及,但我不太了解内部工作原理,因此我可以准确地解释流程是如何进行的。在内部的某个时刻,如果版本增加,update foo WHERE version = @oldversion 会失败,并避免数据库中任何可能的竞争条件。
猜你喜欢
  • 1970-01-01
  • 2016-07-18
  • 2018-10-22
  • 2013-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-27
  • 2015-05-14
相关资源
最近更新 更多