我们有一个系统,我们偶尔会得到一个乐观的锁定异常。我们在代码中已经解决了这个问题,但现在我正在查看JPA 2,并看到它有一个用于处理这个问题的注释(@版本)
我们的问题是,一个表上有多个事务,如果表锁已满,则即使未对相同的记录进行更改,也会导致乐观锁定异常。
我们在JBoss 4.2服务器上使用hibernate,数据库可以是MySQL或SQL服务器。
如果改为使用@Version,这会在两个数据库上都强制执行行锁吗?还是仍然可以看到由全表锁引起的乐观锁定异常?
编辑:
我们实际看到的不是乐观锁定错误,而是死锁:
SQLServerException:事务在另一个进程的锁资源上被死锁,并被选为死锁受害者。重新运行事务。
我们在代码中处理了这个问题,但我想知道@Version在这种情况下是否有帮助
至少在其中一种情况下,此死锁是由表锁引起的,其中两个客户端处理自己的数据。
可能重复:乐观锁定与悲观锁定
乐观锁定异常几乎总是一个有状态并发问题。例如:两个线程加载完全相同的实体,并行更改对象,然后保存它。无论事务(表锁或行锁)如何,发生这种情况时,都会出现乐观锁定异常(请参阅参考问题)。
我很惊讶您在没有版本的情况下获得乐观的锁定异常,在这种情况下,您可能得到了真正的RDBMS OCC错误,但我对此表示怀疑。最有可能发生的情况是,整个对象被区分到行(因为您没有指定版本),在这种情况下,对行的任何更改都将导致乐观锁定异常。请在你的问题中添加例外,这样我就不必假设了。
这取决于您的SQL语句。无论出于何种原因,当事务无法获取所需资源的锁时,都会发生乐观锁。这可能是由于表锁或行锁造成的。没关系。
如果您正在运行需要表锁的SQL查询,那么您在版本字段上就不会有任何运气。默认情况下,MS SQL Server使用行锁。因此,可能您的表很小或缺少主键,或者SQL Server在查询中使用表锁还有其他原因。
您应该调查产生表锁的查询,并尝试对其进行调整。您应该期望偶尔会发生锁定,并在应用程序中处理它。
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作 乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。 乐观锁与悲观锁的具体区别: http://www.cnblogs.com/Bob-FD/p/3352216.html
当我试图理解基于版本的乐观锁定如何防止“最后提交获胜”问题和适当的覆盖时,我遇到了困难。 为了使问题更具体,让我们考虑以下使用 JDBC 的伪代码: 这里,如果其他事务会在更新和提交之间提交其更改呢?如果事务是并发的,那么第一个事务所做的更新尚未提交,因此第二个事务不可见(具有适当的隔离级别),因此第一个事务提交将覆盖第二个交易的更改,而不会出现任何通知或错误。 乐观锁定只是降低了问题发生的概率,
我不确定方法的设计是否恰当。 我们使用乐观锁定,将增量版本放置在每个实体上。这种实体的每次更新都是通过比较和交换算法执行的,该算法的成功与否取决于其他客户端是否同时更新实体。经典的乐观锁定,如hibernate。 我们还需要采取重新尝试的方法。我们使用基于< code>http的存储(etcd ),某些更新请求可能会超时。 这就是问题所在。如何结合乐观锁定和重试?这是我面临的具体问题。 假设我有一
当使用乐观锁定策略时,它可以解决如下并发问题: 但是,如果在极少数情况下,如果第二个事务中的更新是在第一个事务中的udpate之后但在事务提交之前,该怎么办? 我做了一个实验,第二个事务中的更新无法读取“脏”版本,因为第一个事务尚未提交。在这种情况下,第二次交易会失败吗?
在多用户环境中,在同一时间可能会有多个用户更新相同的记录,会产生冲突,解决方案有两种:乐观锁、悲观锁。 悲观锁在这里不讲,自行Google。 乐观锁假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性,不完整则更新失败。 乐观锁实现方式 使用整数表示数据版本号.更新时检查版本号是否一致,如果相等,则更新成功,且版本号+1.如果不等,则数据已经被修改过,更新失败。 使用时间戳来实现。 本质上也
我在Oracle的博客上读到一篇关于JPA和锁定模式的文章。 我不完全理解和锁定模式类型之间的区别。 模式: 当用户选择这种模式时,他必须将EntityManager的状态flush()放到数据库中,以手动增加版本字段。因此,所有其他乐观事务都将失效(回滚)。在事务结束时还会对版本进行检查,以提交或回滚事务。 这似乎很清楚,但什么时候应该使用模式与模式?我看到的唯一标准是,当我希望事务优先于其他事