【问题标题】:Optimistic locking and full table lock乐观锁和全表锁
【发布时间】:2013-03-07 13:32:10
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 恐怕这个问题混淆了乐观并发控制(又名乐观锁定)和表和行上的数据库锁的概念。

标签: jpa


【解决方案1】:

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

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

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

【讨论】:

  • 实际上乐观锁定与“锁”(在本例中为 Hibernate)几乎没有关系。它是一种 ORM hack,通常与表/行锁几乎没有关系。通常是因为并发问题。有特定于 DB 实现的 OCC,但我相信这不是 OP 所说的。
【解决方案2】:

可能重复:Optimistic vs. Pessimistic locking

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

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

【讨论】:

  • 好吧,我查看了我们的 jira 服务器,发现这实际上是我们遇到的死锁问题,我们在代码中进行了处理。当我阅读@Version 时,我只是问自己这是否可以帮助我们,或者是否是另一个问题。
  • 有点不清楚你在问什么。正如我在回答中所说,乐观锁定不会导致死锁,无论@Version如何,休眠仍然会这样做。所以在这方面使用不会有所作为。
猜你喜欢
  • 1970-01-01
  • 2011-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-29
  • 2013-06-30
相关资源
最近更新 更多