如何在与用户思考时间之间的长时间对话中实现悲观锁定,以休眠为例?

how to implement pessimistic locking in long conversation with user think time in between, using hibernate as example?

因为悲观锁只能应用于单个数据库事务。并在用户思考时间内保持数据库事务打开,在数据库中持有锁被认为是反模式,那么在用户思考时间之间实现悲观锁的正确方法是什么?

我知道如何在与用户思考时间之间的长时间对话中实现乐观锁定,只是不知道如何在与用户思考时间之间的长时间对话中实现悲观锁定。

简短的回答是没有 "simple recipe" 可以做到这一点,Hibernate 或任何其他 ORM 框架也没有现成的解决方案。

长答案:

您必须弄清楚如何实现一些功能,使您的应用程序能够为您的 "long conversation" 模拟数据库锁定行为。

最重要的是确保一旦用户开始使用一条信息(数据库行或一组对象,无论您的情况如何),该信息都不会 used/manipulated 被任何人使用其他用户。此外,您还必须确保您有一些关于发布信息的政策,无论是在用户完成操作时,还是在经过一定时间后(您不希望永远锁定您的信息)。

由于我不了解您的应用程序的详细信息,因此我将提供一个抽象示例,以作为您案例的灵感来源。当然这不是唯一的解决方案。

请记住,每个步骤都将包含在单个事务中,因为最后,您的长时间对话将是您网络应用程序中的一系列请求。

此外,假设问题标签中的信息,此答案旨在为连接到数据库的简单网络应用程序提供解决方案。无 "fancy exotic" 架构。

在需要这种控制的给定 table 中,添加 2 列:一列是用户 ID,另一列是时间戳。这将控制谁在一行上有 "lock",以及它被获取的时间。

当用户开始使用 table 行中包含的数据时,您的应用程序将使用用户 ID 和当前 date/time 更新该行。 这是最重要的一步,因为您必须正确处理并发。如果不止一个用户试图获取该行的 "lock",您的应用程序必须让出 只有一个用户 的锁。此步骤很可能需要在单个事务中使用数据库锁。确保此步骤快速且不附加到其他操作,因此数据库锁定不会对您的应用产生重大影响。

用户操作完数据后,应用程序只需将用户ID和时间戳置为空,之后其他用户就可以使用了。

如果用户出于某种原因没有完成任务,您将不得不应用某种 "release" 策略。在简单的情况下,一个简单的时间到期将解决这个问题。如果给定用户尝试在已锁定的行上获取 "lock",您的应用程序将检查时间戳。如果时间戳已过期,新用户将覆盖锁定。如果不是,则该行不可用。

还有其他更复杂的场景。如果在您的过程中,在操作完全完成之前数据库中的信息发生了更改(假设用户进行了各种信息更改,并且在用户完成操作和 "releases" 行之前将它们发送到数据库) ,也许你必须弄清楚如何实现回滚。也许留数据"half manipulated"可以,也许不行,看你的业务需求。

长话短说:

  • 锁定是由您数据库中的列组成的 table
  • 你的代码控制锁

  • 用户尝试获取锁

  • 如果行空闲,或者之前的锁已过期,则获取锁
  • 操作完成后,锁被删除

请仔细考虑此建议中的任何一条是否适用于您的情况。

希望对您有所帮助。