Java hibernate乐观锁机制
我对hibernate乐观锁(专用版本方式)非常好奇,我检查了hibernate源代码,它告诉我在当前事务提交之前检查版本,但是如果在它从DB查询版本列之后发生了另一个事务提交(在很短的时间间隔内),然后当前事务认为没有更改,因此旧事务将被错误地替换 EntityVerifyVersionProcess.javaJava hibernate乐观锁机制,java,database,hibernate,transactions,optimistic-locking,Java,Database,Hibernate,Transactions,Optimistic Locking,我对hibernate乐观锁(专用版本方式)非常好奇,我检查了hibernate源代码,它告诉我在当前事务提交之前检查版本,但是如果在它从DB查询版本列之后发生了另一个事务提交(在很短的时间间隔内),然后当前事务认为没有更改,因此旧事务将被错误地替换 EntityVerifyVersionProcess.java @Override public void doBeforeTransactionCompletion(SessionImplementor session) {
@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"
);
}
}
这种情况可能吗
希望有DB领域的专家能在这方面帮助我
非常感谢。快速浏览代码后,
EntityVerifyVersionProcess
用于读取事务,因此不会导致数据丢失。这只会检查事务提交时是否没有返回已经过时的数据。对于readcommitted
事务,我想这可能会返回立即过时的数据,但如果不详细说明,很难说
另一方面,写事务使用EntityIncrementVersionProcess
,这是一个完全不同的beast,不存在竞争条件
public void doBeforeTransactionCompletion(SessionImplementor session) {
final EntityPersister persister = entry.getPersister();
final Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), session );
entry.forceLocked( object, nextVersion );
}
那会使它破碎无用。不是很好的广告“使用乐观锁定,它通常不会损坏您的数据!”。嗯,实际上我不认为这是一个重复的问题,这个问题是关于乐观锁定机制的,但我不是…你不是什么?这似乎正是你所说的,不,事情不可能破裂。如果乐观锁定失败,将回滚一个事务。hibernate源代码使用SQL“从xx选择版本”的方式检查版本更改,而不是在doso中附加“WHERE VERSION=?”子句。它(OptimisticLock)使用“SELECT xxx FOR UPDATE”的方式锁定,而不是在开始时锁定长事务的记录,这很有意义,谢谢你的帮助。不,不。没有选择更新,这将在事务期间锁定记录。只是内部工作并不简单,问题中的代码不处理更新,只处理选择。如果您正在执行更新,则会涉及到其他
*进程
类,但我不太了解内部工作原理,因此无法准确解释流程的运行方式。在内部的某个点上,有更新foo,其中version=@oldversion
,如果版本增加,它将失败,并避免数据库中任何可能的争用条件。