当前位置: 首页 > 知识库问答 >
问题:

乐观锁定和覆盖

华誉
2023-03-14

当我试图理解基于版本的乐观锁定如何防止“最后提交获胜”问题和适当的覆盖时,我遇到了困难。

为了使问题更具体,让我们考虑以下使用 JDBC 的伪代码:

connection.setAutoCommit(false);
Account account = select(id);
if (account.getBalance() >= amount) {
   account.setBalance(account.getBalance() - amount);
}
int rowsUpdated = update(account); // version=:oldVer+1 WHERE version=:oldVer
if (rowsUpdated == 0) throw new OptimisticLockException();
connection.commit();

这里,如果其他事务会在更新和提交之间提交其更改呢?如果事务是并发的,那么第一个事务所做的更新尚未提交,因此第二个事务不可见(具有适当的隔离级别),因此第一个事务提交将覆盖第二个交易的更改,而不会出现任何通知或错误。

乐观锁定只是降低了问题发生的概率,而不是总体上防止了问题的发生吗?

共有1个答案

黎腾
2023-03-14

数据库“事务”的概念是,它应该提供跨多个概念操作的“一致性”保证。数据库负责实施这一点。因此,当事务提交时,如果数据库能够确保事务期间发生的所有事情仍然有效,它应该只允许事务完成。

实际上,数据库通常会处理此问题,一旦其中一个更新成功,相关行将被写锁定,直到相关事务完成。因此,其中一个更新肯定会失败。

注意:这也需要在jdbc连接中适当的隔离级别。隔离级别确保在更新之前对当前值所做的测试在写入时仍然适用。

 类似资料:
  • 我们有一个系统,我们偶尔会得到一个乐观的锁定异常。我们在代码中已经解决了这个问题,但现在我正在查看JPA 2,并看到它有一个用于处理这个问题的注释(@版本) 我们的问题是,一个表上有多个事务,如果表锁已满,则即使未对相同的记录进行更改,也会导致乐观锁定异常。 我们在JBoss 4.2服务器上使用hibernate,数据库可以是MySQL或SQL服务器。 如果改为使用@Version,这会在两个数据

  • 我不确定方法的设计是否恰当。 我们使用乐观锁定,将增量版本放置在每个实体上。这种实体的每次更新都是通过比较和交换算法执行的,该算法的成功与否取决于其他客户端是否同时更新实体。经典的乐观锁定,如hibernate。 我们还需要采取重新尝试的方法。我们使用基于< code>http的存储(etcd ),某些更新请求可能会超时。 这就是问题所在。如何结合乐观锁定和重试?这是我面临的具体问题。 假设我有一

  • 悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。 乐观锁与悲观锁的具体区别: http://www.cnblogs.com/Bob-FD/p/3352216.html

  • 我在Oracle的博客上读到一篇关于JPA和锁定模式的文章。 我不完全理解和锁定模式类型之间的区别。 模式: 当用户选择这种模式时,他必须将EntityManager的状态flush()放到数据库中,以手动增加版本字段。因此,所有其他乐观事务都将失效(回滚)。在事务结束时还会对版本进行检查,以提交或回滚事务。 这似乎很清楚,但什么时候应该使用模式与模式?我看到的唯一标准是,当我希望事务优先于其他事

  • 在多用户环境中,在同一时间可能会有多个用户更新相同的记录,会产生冲突,解决方案有两种:乐观锁、悲观锁。 悲观锁在这里不讲,自行Google。 乐观锁假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性,不完整则更新失败。 乐观锁实现方式 使用整数表示数据版本号.更新时检查版本号是否一致,如果相等,则更新成功,且版本号+1.如果不等,则数据已经被修改过,更新失败。 使用时间戳来实现。 本质上也

  • 本文向大家介绍说一下乐观锁和悲观锁?相关面试题,主要包含被问及说一下乐观锁和悲观锁?时的应答技巧和注意事项,需要的朋友参考一下 乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。 悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。 数据库的乐观锁需要自