防止覆盖 PHP 中的并发表单

Preventing overwrites from concurrent forms in PHP

我们正在建立一个系统,允许部门在此处编辑记录。他们的分工不明确,过去他们遇到过这样的问题,即不止一个人将数据加载到 Web 表单中,进行编辑,然后将这些编辑发送到记录中。不可避免地,速度较慢的编辑器会用页面加载时加载的旧数据覆盖速度较快的编辑器新编辑的数据。

目前,我们有一个白板解决方案,它会使用对数据最后修改时间的更改来拒绝第二次写入数据的请求,并在该数据发布时传递错误消息。

然而,该部门的成员更喜欢文件锁样式的系统——在该系统中,他们被通知另一个用户在数据集中之前被允许访问数据。超时将不可避免地太短或太长,具体取决于一天,并且不能依赖这些特定用户以某种方式 "log out"。

我只是想知道是否还有其他人对此实施了解决方案,如果是,如何?

我们在 Apache 2.2 上 运行 PHP 5.6 并在 Zend Framework 2.4 中构建。并不是说这些都与问题有任何关系,但不可避免地会有人问。

为什么不在 edit_in_progress 的 table 行上设置一个标志?如果用户单击编辑并且该标志已设置,则失败并显示一条消息说其他人正在编辑它(也许还可以考虑为谁正在编辑它设置一个字段,这样他们就可以在保存之前返回并继续他们的编辑)。保存后,取消设置这两个字段,并允许下一个用户锁定该行。

向 table locked_by_user_idlocked_time 添加 2 列。

在允许用户进入 "edit" 视图之前,请检查是否设置了这些值以及 locked_time 是否在过去 10 分钟内。你应该记录锁定时间而不是二进制标志的原因是,正如你所说,有些人忘记注销或者可能没有完全注销(例如,他们可以关闭浏览器)。

当某人能够获取锁时,设置一个每 5 分钟运行一次的 setInterval,它通过 ajax 调用重新获取锁。有人可能仍然会忘记离开 "edit" 屏幕,但在这种情况下,您可以允许其他人覆盖锁定,如果发生这种情况,您可以让 ajax 调用退出 "edit" 屏幕。重新获取锁失败。

假设您正在使用数据库,但不知道您正在使用的数据库架构,这将是一个通用的答案。

您需要给每条记录一个标识符,该标识符设置为非唯一的。通过这个,我的意思是每条记录都可以被识别为 record_1record_2 ... record_n 但是这个标识符可以在 table.

中出现多次

编辑记录时,不要直接更新记录而是创建一条新记录

  • 时间戳
  • 具有原始 record_n 标识符

此外,向记录添加一个字段以提供其当前状态(例如 stableediting?)和一个提供编辑开始的字段 date/time 如果正在编辑已编辑

有了这个,当有人想要编辑一条记录时(例如,record_2),你检索这条记录的最新数据并检查它的状态(如果标记为 editing 然后报告这个并防止并发编辑)。

当他们提交更改时,会在数据库中创建一条新的带时间戳记的记录,您将新旧记录标记为 stable。

使用它,您还可以创建用于审核更改的书面记录

关于徘徊 off/retire/die 并使记录处于编辑状态的人,创建一个计划作业,在预设的分钟数(60?)[=18 后将状态重置为 "stable" =]