1

我正在开发一个相对简单的自定义 Web 应用程序,后端有一个 MySQL MyISAM 数据库。不知何故,我想避免经典的并发覆盖问题,例如用户 A 覆盖用户 B 的编辑,因为 B 在 A 完成之前加载并提交了一些编辑表单。

这就是为什么我想以某种方式在显示编辑表单时锁定一行。然而...

  • 正如我所说,我正在使用 MyISAM,据我所知,它不支持行级锁。此外,我不确定是否建议将“真正的”MySQL 锁保持几分钟。
  • 我对事务知之甚少,但从我所见,看起来它们应该在一个连接中使用。
  • 使用像 Git 这样的某种冲突合并系统并不是一个真正的选择。

行将保持锁定几分钟。并发性非常低:任何时候都有六个用户在使用该应用程序。

我现在正计划使用一个表格,其中包含有关哪个用户在做什么以及从什么时候开始的详细信息。然后,当其他一些用户最近打开它(例如正在处理它)时,应用程序可以决定不显示编辑表单。这个假锁将在保存表单时被删除。

这行得通吗?我应该怎么做才能避免死锁、活锁和所有这些东西?

4

2 回答 2

3

你可以实现一个锁,最简单的可能是向你想要锁定的数据添加两个字段(lock_created Datetime,locked_by int)。然后在编辑页面上(也可能在编辑按钮上)检查 (lock_created + lock_interval) < now() - 如果没有,数据被锁定以进行编辑,并且应该通知用户。(请注意,您始终需要在编辑页面上进行检查,而不仅仅是在编辑按钮上。)同样在提交页面上,您需要检查用户是否仍然拥有提交的锁定。(见下文。)

其中一个困难的部分是当有人编辑但未能在锁定间隔内提交时该怎么办。所以:

  1. lock_interval 为 2 分钟。
  2. 在时间 0:00 时,Alice 锁定了页面,编辑了一些东西,但接到了一个电话并且没有提交她的更改
  3. 在 2:30,Bob 检查了页面,因为 Alice 的锁已经过期,所以得到了编辑锁,并且编辑了
  4. 在 3:00 时,Alice 回到她的比赛中,按下提交 -> 冲突。

有人没有提交他们的数据。如果您将锁设置为过期,则无法解决此问题。(如果不这样做,锁可以永远保留。)您只能决定优先考虑哪个(使用 Bob 创建的新锁可能最简单)并通知另一个页面已过期并且数据将不会t 被提交,并将他们的编辑交还给他们以重做。

A note on the table structure: you could create a table 'locks' with fields 'table_name, row_id, lock_created, locked_by' but it probably won't be the easiest way, since joining on variable table names is complex and confusing. Also, there is probably no use to have a single place for all locks to be stored. For a simple mechanism, I think adding uniform fields to every table you want to implement the locking mechanism is easier all around.

于 2011-06-12T13:11:53.173 回答
0

在这种情况下,您绝对不应该使用行级锁。

您可以使用乐观锁定,这基本上意味着您对每一行都有一个版本字段,该字段在保存该行时递增。在保存之前,请确保版本字段与加载该行时的版本字段相同,这意味着自您读取该行以来没有其他人保存过任何内容。

于 2011-06-12T11:52:47.713 回答