3

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

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

如果我们改为使用@Version,这是否会在两个数据库上强制执行行锁定,或者我们仍然可以期望看到由全表锁定引起的乐观锁定异常?

编辑:
我们实际看到的不是乐观锁定错误,而是死锁:

SQLServerException:事务在锁定资源上与另一个进程死锁,并已被选为死锁牺牲品。重新运行事务。

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

4

2 回答 2

1

可能重复:乐观与悲观锁定

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

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

于 2013-03-07T15:14:09.823 回答
1

这取决于您的 SQL 语句。每当事务无论出于何种原因未能获得所需资源的锁时,都会发生乐观锁。这可能是由于表锁或行锁造成的。没关系。

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

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

于 2013-03-07T14:57:44.610 回答