乐观锁定和全桌锁

时间:2013-03-07 13:32:11

标签: jpa

我们有一个系统,我们偶尔得到一个乐观的锁定异常。我们已经在代码中解决了这个问题,但现在我正在研究JPA 2并看到它有一个注释(@Version)来处理这个问题。
我们遇到的问题是多个事务正在处理一个表,并且使用完整的表锁定会导致乐观锁定异常,即使没有对相同的记录进行更改。

我们在JBoss 4.2服务器上使用hibernate,数据库可以是MySQL或SQL Server。

如果我们改为使用@Version,这会对两个数据库强制执行行锁定,还是我们仍然期望看到由全表锁定导致的乐观锁定异常?

修改
我们实际看到的不是乐观的锁定错误,而是一个死锁:

  

SQLServerException:事务已在锁资源上死锁   另一个进程并被选为死锁受害者。重新运行该交易。

我们在代码中处理这个问题,但我想知道@Version在这种情况下是否有任何帮助。
至少在其中一种情况下,这种死锁是由表锁引起的,其中两个客户端正在处理自己的数据。

2 个答案:

答案 0 :(得分:1)

这取决于您的SQL语句。只要事务无法以任何原因获取所需资源的锁定,就会发生乐观锁定。这可能是由于表锁或行锁。没关系。

如果您正在运行需要表锁的SQL查询,那么您将无法获得版本字段。默认情况下,MS SQL Server使用行锁。因此,您可能有小表或缺少主键,或者SQL Server在查询中使用表锁时还有其他原因。

您应该调查生成表锁并尝试调整它的查询。您应该期望偶尔发生锁定并在您的应用程序中处理它。

答案 1 :(得分:1)

可能重复:Optimistic vs. Pessimistic locking

乐观锁定异常几乎总是有状态并发问题。例如:两个线程加载完全相同的实体,并行更改对象然后保存它。 无论事务(表或行锁定),当发生这种情况时,您将获得乐观锁定异常(参见引用的问题)。

我很震惊你的乐观锁定异常没有@Version在这种情况下你可能会变得真实RDBMS OCC error但我对此表示怀疑。最可能发生的事情是整个对象被差异化到行(因为你没有指定@Version),在这种情况下,对行的任何更改都将导致乐观锁定异常。请在您的问题中添加例外,这样我就不必假设了。