有没有办法在特定的时间段内锁定MySQL表中的记录?

时间:2015-05-16 23:39:57

标签: mysql

我有一张表格,其中包含一所大学学生家长的数据。将向每位家长发送一封电子邮件,其中包含指向网页的链接,该网页将显示我们当前记录的父数据(姓名,电子邮件地址,邮寄地址,就业信息等),并且能够编辑数据为了更新我们的记录。

由于每个父母都会收到相同数据的链接,并且能够更新相同的字段,因此父母双方可能同时打开数据,然后一个父母提交更改,然后另一个父母提交更改提交更改将覆盖第一位家长提交的更改。

为了避免这种情况,我想到了使用我读过的方法,其中父数据记录中存在时间戳字段,并且该时间戳用作表单上的隐藏字段。然后,如果父母双方都加载了表单,则他们都会在表单中存储相同的时间戳。但是,当第一个父提交她/他的更新时,时间戳字段将更新,并且当第二个父提交表单时,来自她/他的表单的时间戳将与表中的时间戳不同,并且程序(Perl CGI)会提醒第二个父母这个事实,并告诉他们重新加载表格或冒险覆盖第一个父母提交的数据。

这样可行,但是我创建此表单的人询问,如果第一个父级加载表单后,是否有办法锁定表中的记录,并且如果第二个父级在锁定存在时尝试加载表单,则表单将告诉他们等到以后(或者说这个效果)。锁定将一直存在,直到表格由父母提交,或者直到一小时(或某个特定时间段)已经过去。这甚至可以吗?我一直在谷歌搜索,并没有看到这方面的具体例子。

是否有一些更好的解决方案可以防止两个人更新同一记录,第二个提交者覆盖第一个提交的数据。

感谢您提供的任何帮助!

     Doug

*******通过" inspiredcoder来解决评论,"这里有一些关于我在这里关注的细节:

我试图避免发生的事情是父母1打开表单并开始更改数据。在父级1提交这些更改之前,父级2打开表单并开始对父级1正在编辑的相同字段进行不同的更改。父级1然后提交她/他的更改。然后父母2提交她/他的更改,覆盖父母1所做的更改。

我更喜欢的是,如果父1打开表单,父母2甚至无法开始进行更改。父母双方所做的更改需要被捕获,而不是被覆盖。

我在初始帖子中描述的使用时间戳的方法可用于防止父2覆盖数据,但这也意味着他们必须重新加载表单以查看提交的更改父母1,并且在这样做之前,他们将失去他们在尝试提交并获得通知重新加载之前在表单中所做的任何编辑。我想避免他们不得不重新输入他们的更改,而实现这一点的唯一方法似乎是阻止他们甚至打开表单,如果它已经被编辑,但我想要那个"锁"在一个小时左右的时候,表单/数据超时,以防父母1离开表单打开但未提交。

*****通过" ThisSuitIsBlackNot"回答问题:每个家长都可以编辑相同的字段。一个领域要求父母参与的活动。让我们说父母1进入五项活动。如果父母2在提交父母1的编辑之前看到该表格,他/她可以输入完全不同的项目,在提交时将覆盖父母1提交的活动。另一方面,父母2可以是在父母1完成她/他的编辑之前停止访问表单,然后当父2 可以加载表单时,她/他将看到父1输入的所有内容,而不是空表单字段,并且可以选择修改父1提交的内容,完全覆盖它,或者不做任何更改。

2 个答案:

答案 0 :(得分:2)

有一个原因,你没有找到任何关于如何做到这一点的信息。这是一个非常棘手的问题,无论您使用哪种技术堆栈,都无法找到一个好的解决方案。在您的情况下,我不相信它实际上是一个非常重要的问题需要解决,因为数据似乎并不重要或关键任务。此外,如果有变化,它们可能会相同。

我在很多设计讨论中都遇到过这个问题。经过几个小时的争论后,结果总是一样的:最后一个胜利。

也就是说,您可以尝试以下几个更简单的想法:

  • 只要该页面上的数据发生变化,只需向父母(或任何注册为监护人的人)发送电子邮件即可。这个解决方案简单易行,易于实现。如果您已经在应用程序的其他部分使用电子邮件服务,那么它几乎变得微不足道。
  • 不那么简单:每当请求编辑数据时,创建数据的哈希值,然后将响应发送回客户端。发送编辑后的数据以更新行时,请根据哈希检查数据。如果哈希值不匹配,则意味着其他人在查看数据时修改了数据。这个解决方案的问题在于你必须创建这些哈希并通过应用程序的多个层将它们拖拽,这使得编程变得非常重要。

此声明引起了我对你的OP的后续编辑的注意:

  

父母双方所做的改变都需要被捕获,而不是   覆盖。

这个单一的商业规则实际上让事情变得非常简单。您需要做的就是在没有唯一标识符(可能是0或-1)时始终创建对象。当对象确实有ID时,意味着它们已经创建,您只需更新即可。

此处假设编辑可能会在相同数据上以非破坏性方式执行。例如一位父母创建一个活动而另一位父母正在编辑它。可能存在重复活动,但这种情况很容易通过删除解决。

这样,没有一个家长可以盲目且不知不觉地覆盖对方的数据。

无论你做什么,都不要试图找到一个完美的解决方案。它不会发生。我知道,我已经写了超过15年的业务应用程序。将您的时间和才能应用于您能够做到的事情,应用程序及其业务规则。

答案 1 :(得分:0)

我建议阅读数据库隔离级别。我相信MySQL默认为可重复读取。您可以通过运行“SHOW GLOBAL VARIABLES LIKE'tx_isolation'来确认数据库级别的隔离级别;”此配置中的每个事务都已锁定。无论是获得行级还是升级,都取决于查询如何触及索引等因素。如果您触发事务A以更新记录然后触发事务B,则事务B已处于保持模式,直到事务A在此配置中完成其工作。如果将其设置为read commited,则读取不再通过锁定相互阻塞(更新等仍然存在锁定)。代替对读取的隐式锁定,您可以使用select for update显式尝试强制读取锁定。

我提到了对锁定机制的研究,因为在没有对后端DB机制的极端了解的情况下尝试暴力锁定可能会导致死锁中心。

在您的场景中,似乎更多的是用户感知他们在提交更改时所阅读的内容是最新的。 DB真的按照设计完成了它的工作。我已经看到了解决这个用户感知问题的架构,它只允许一个记录中的一个用户(在其他人用户的情况下锁定其他用户),在某些中间件代码中处理等等。或者通过使用SOA架构推送向记录中的用户发出通知,告知其他用户发生了更改。