当用户编辑行时,是否应该将行锁定在云数据库中?


12

我正在创建一个桌面应用程序,将数据持久存储在云中。我关心的一个问题是开始在应用程序中编辑项目,并将其保留一段时间会导致数据过时。如果两个人同时尝试编辑同一项目,则显然也会发生这种情况。当他们完成编辑并要保存数据时,我要么需要覆盖数据库中当前存在的内容,要么检查他们在上一次更改之后是否开始编辑,或者迫使他们放弃更改,或者给他们选择冒险的选择覆盖他人的更改。

我想增加一个字段is_lockedlock_timestampdb表。当用户开始编辑项目时,该行将is_locked变为true并将锁定时间戳记设置为当前时间。然后,我将拥有一段时间的锁定时间(例如5分钟)。如果其他任何人尝试编辑该项目,他们将收到一条消息,指出该项目已被锁定,并且锁定自动失效。如果用户在编辑时走开,则锁会在相对较短的时间后自动过期,一旦这样做,将警告用户锁已过期,并在刷新数据后被迫重新开始编辑。

这是防止覆盖陈旧数据的好方法吗?是不是太过分了(我不希望单个帐户同时使用多个应用程序)。

(我还要担心的是,有2个人为同一物品锁上了锁,但是我认为这是我可以接受的比赛条件。)


1
“我要担心的另一个问题是2个人要为同一物品获得一把锁,但是我认为这是我可以接受的竞争条件。”-在获取锁的过程中使用数据库事务应该可以防止这种竞争条件。
Jules

大多数数据库引擎(至少是关系型的)都对此提供了内置支持。在RDBMS世界中,这是一个非常普遍的概念,即使您告诉它您要乐观锁定还是悲观锁定,甚至“玩具”数据库也能很好地处理它。无论如何,我认为您不需要通过任何方式来构建它:检查数据库引擎上的选项以了解如何使用它。
jleach

您的应用程序是桌面应用程序(胖客户端)这一事实并没有多大区别。可以采用与高度可用的多实例服务器应用程序相同的方式进行设计。
Hosam Aly

Answers:


19

术语对您有帮助。您在此处描述的内容称为“悲观锁定”。这种方法的主要替代方法是“乐观锁定”。在悲观锁定中,每个参与者都必须在更新记录之前锁定记录,并在更新完成后释放锁定。在乐观锁定中,您假设没有其他人正在更新记录并尝试。如果记录被其他参与者更改,则更新失败。

如果两个参与者同时更新同一事物的机会很小,通常最好使用乐观锁定。悲观主义通常在机会很高或您需要知道更新将在开始之前能够成功的情况下使用。以我的经验,乐观锁定几乎总是可取的,因为悲观锁定有很多固有的问题。您的问题涉及到最大的问题之一。用户可以锁定记录进行编辑,然后再去吃午餐。您的缓解措施将对此有所帮助,但是用户体验不会比乐观方法更好,并且可能会更糟。例如,一个用户打开一条记录,开始更新该记录,而其老板则出现在办公桌前。另一个用户尝试编辑记录。它是锁着。第二个用户继续尝试,并且在5分钟后,锁到期,第二个用户更新记录。第一个用户返回到屏幕,尝试保存并被告知他们丢失了锁。现在,在相同的情况下,除了使用乐观锁定之外,其他所有方面都相同,第一个用户的体验几乎相同,但是第二个用户不必等待5分钟。

通过为锁值实现乐观锁定,可以极大地改善您布置的方案,但是我的直觉是,乐观锁定对于整个过程来说可能是可以的,您可以摆脱is_locked字段。

您没有提供您正在使用的“云数据库”。在实施自己的解决方案之前,您可能应该研究该功能,以了解是否具有内置功能。

这是基本的配方:有一个版本号字段,而不是is_locked字段。检索记录时,将拉出记录的当前版本。更新时,使更新取决于所检索内容的版本字段,并在成功后增加。如果版本不匹配,则更新无效,您将其报告为失败。


这是一个非常有用的答案。您能解释一下为什么很少有“冲突”时不鼓励悲观锁定吗?纯粹是因为它需要进入数据库才能开始编辑,还是因为额外的复杂性或其他原因?谢谢!
yitzih

3
@yitzih一些建议阅读:Fowler等人,《企业应用程序体系结构的模式》。这个问题整整一章,对所有选项和选择它们的原因进行了很好的讨论。
Jules

2
@Jimmy-您的回答很好。在某些情况下,向我报告错误是不够的。考虑一种情况,用户花了几分钟来更新记录。在那种情况下,仅失败可能还不够好,一个人可能想给用户机会将他们的机上更改与另一用户提交的更改进行合并。我应该说,根据您的要求,乐观锁定可能需要解决冲突。
乔恩·雷诺

3
值得一提的是,悲观锁定更容易向客户解释。如果您写一条消息,表示客户端无法访问该记录,因为该记录当前正在由另一个编辑,则客户端既可以理解,也可以接受。如果您在保存后告诉客户端无法进行保存,因为该保存已由另一个用户7/10更新,则客户端将感到沮丧,并且/或者需要对此奇怪程序行为的解释。
尼尔

2
@Neil是的,我认为这是为什么在更合适乐观时使用悲观锁定的原因。通常,工作流程使冲突很少发生。
JimmyJames

0

@JimmyJames的答案中,我们可以看到问题实际上与用户体验有关

这完全取决于上下文。更新记录需要多少时间和精力?多个用户多久要更新同一文档?

例如,如果您的用户通常花几秒钟来更新记录,并且几乎没有争用,那么乐观锁定可能是解决之道。在最坏的情况下,用户将不得不花几秒钟(可能最多一分钟)来更新文档。

如果您的文档具有很高的争议性但结构良好,则可以允许他们以30秒为增量锁定各个字段,并显示计时器或不打扰的通知以允许他们扩展锁定。

但是,如果您的用户花费大量时间或精力,则应考虑其他方法。您的记录结构合理吗?您能否向用户显示服务器上的版本与他们尝试保存的版本之间的比较(差异)?您能否强调差异?您可以让他们合并更改吗?想想您想要使用源代码控制工具的经验。您真的不想被迫再次编写所有这些代码!

您可以查看Google文档以获取其他启发。也许您可以向用户显示已保存新版本的通知。也许您可以向他们展示打开记录的人数,以便他们可以选择在争议较小的时间回来。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.