我想使用以下示例来描述该问题:
让我们假设我们正在开发应用程序(基于Hibernate JPA和Spring),允许其用户执行两种必须以可序列化模式为每个用户执行的事务操作。至于应用程序必须同时强大且性能良好,我们可以使用ReentrantLock周围的某种包装器进行同步:
void operation1(user) {
userLockWrapper.lock(user.id); //gets ReentrantLock for specified id from internal map and locks it
try {
//start transaction
//perform operation
//commit transaction
} finally {
userLockWrapper.unlock(user.id).
}
}
void operation2(user) {
userLockWrapper.lock(user.id); //same wrapper instance as in operation1
//same logic as in operation1
}
现在让我们假设为了提高可扩展性,我们将系统划分为两个独立的模块,这些模块在不同的VM中运行并使用相同的数据库,其中第一个负责operation1,第二个负责operation2。首先想到的决定是使用悲观锁,例如:
@Transactional
void operation1(user) { //same goes for operation2
//firing extra select for update sql statement here
entityManager.find(User.class, user.id, LockModeType.PESSIMISTIC_WRITE)
//performing operation
}
我想知道是否有更优选的解决方案。希望得到社区的一些建议。
答案 0 :(得分:2)
是的。使用乐观锁定。您只需向实体添加@Version带注释的持久字段,并了解其工作原理。阅读http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#transactions-optimistic
每次Hibernate将实体写入数据库时,它会检查存储的版本是否仍然与内存中的版本相同,并且会增加此版本。如果版本不匹配,则抛出一个使事务回滚。
这将允许最佳吞吐量,它也是唯一可以在两个事务中使用的系统:第一个事务加载对象,用户修改它(可能需要几分钟),第二个事务合并对象。 / p>