因为悲观锁只能应用于单个数据库事务。并在用户思考时间内保持数据库事务开放,而数据库中持有的锁被认为是反模式,那么在用户思考时间介于两者之间的情况下实现悲观锁的正确方法是什么?
我知道如何在与用户之间思考时间较长的对话中实现乐观锁定,只是不知道如何在与用户之间思考时间较长的对话中实现悲观锁定。
答案 0 :(得分:1)
简短的回答是,没有这样做的“简单方法”,也没有Hibernate或任何其他ORM框架提供的现成解决方案。
长答案:
您将必须弄清楚如何实现一些功能,这些功能将使您的应用程序可以为“长时间对话”模拟数据库锁定行为。
最重要的是要确保一旦用户开始使用一条信息(数据库行或一组对象,无论您的情况如何),该信息将不会被其他任何用户使用/操纵。此外,您还必须确保在用户完成操作时或经过一定时间后(您不希望永久锁定信息)有一定的政策来发布信息。>
由于我不了解您的应用程序的详细信息,因此我将举一个抽象的示例,作为您案例研究的灵感。当然,这不是唯一的解决方案。
请记住,每一步都将包含在一个事务中,因为最终,漫长的对话将是Web应用程序中的一系列请求。
此外,假设来自问题标签的信息,此答案的目的是在连接到数据库的简单Web应用程序中寻求解决方案。没有“奇特的异国情调”架构。
在需要这种控制的给定表中,添加2列:一列将是用户ID,另一列是时间戳。这将控制谁连续拥有“锁”以及获取该锁的时间。
当用户开始使用表格行中包含的数据时,您的应用将使用用户ID和当前日期/时间更新该行。 这是最重要的步骤,因为您必须正确处理并发性。如果有多个用户尝试在该行上获取“锁”,则您的应用必须为仅一个用户放弃该锁。此步骤很可能需要在单个事务中使用数据库锁。确保此步骤快速并且没有附加到其他操作,因此数据库锁定不会对您的应用产生太大影响。
在用户处理完数据后,应用程序只需将用户ID和时间戳设置为null,然后其他用户就可以使用它。
如果用户由于某种原因未完成任务,则必须应用某种“发布”策略。在简单的情况下,简单的时间到期将解决此问题。如果给定的用户尝试在已经具有锁定的行上获取“锁定”,则您的应用程序将检查时间戳。如果时间戳记过期,则新用户将覆盖该锁定。如果没有,则该行不可用。
还有其他更复杂的方案。如果在您的处理过程中,信息在操作完全完成之前已在数据库中更改(例如,用户进行了各种信息更改,并在用户完成操作并“释放”该行之前将它们发送到了数据库),则可能您将必须弄清楚如何实施回滚。保留数据“半操纵”可能没有问题,这取决于您的业务需求。
简而言之:
您的代码控制锁
用户尝试获取锁
请仔细考虑以下建议是否适用于您的情况。
我希望这会有所帮助。