Php 通过合并到MySQL保存不断更新的数据数组(可能存在并发问题)

Php 通过合并到MySQL保存不断更新的数据数组(可能存在并发问题),php,mysql,updates,Php,Mysql,Updates,目前,我们有一个PHP基础,在这个基础上,用户可以登录到他们的帐户。我们的网站相当大,我们的开发人员希望能够存储任意数量的数据,以使每个用户受益(因此,可能是他们在页面上输入的内容,我们可以根据他们返回页面时所做的操作,使用不同的值加载页面) 问题是,我不确定存储这种持久性数据的最佳方法。我最初的想法是将其存储在MySQL数据库中的一个序列化PHP数组中。这很好,只是我们遇到了一个并发性问题,用户打开一个页面,该页面会拉取数组,决定需要修改,并且会这样做,同时,他们在另一个选项卡中打开一个页面,

目前,我们有一个PHP基础,在这个基础上,用户可以登录到他们的帐户。我们的网站相当大,我们的开发人员希望能够存储任意数量的数据,以使每个用户受益(因此,可能是他们在页面上输入的内容,我们可以根据他们返回页面时所做的操作,使用不同的值加载页面)

问题是,我不确定存储这种持久性数据的最佳方法。我最初的想法是将其存储在MySQL数据库中的一个序列化PHP数组中。这很好,只是我们遇到了一个并发性问题,用户打开一个页面,该页面会拉取数组,决定需要修改,并且会这样做,同时,他们在另一个选项卡中打开一个页面,该页面会拉取数组的同一原始副本,决定需要不同的修改,并将其写入数据库,因此只有一个页面“获胜”,一个更改将丢失。很有可能(目前确实如此),用户在不同的选项卡中打开我们网站的多个页面,因此我们需要对此进行说明


第二个解决方案只是第一个解决方案的扩展,我们可以在MySQL中存储更新时间的时间戳,如果整个阵列在开发人员拉取后已经更新,那么他们需要重新拉取整个阵列,检查它们的更改是否仍然相关,然后重新提交,这样它就会成为新的阵列。这看起来有点混乱,但这是我目前拥有的最好的解决方案,有人有其他想法吗?

必须编写更多代码来检测出现了另一个更改,并且拒绝用户的编辑,或者尝试合并更改,这是很常见的

例如,StackOverflow就是这样做的。如果你正在编辑一篇文章,而其他人也在编辑它,并首先保存他们的更改,当你提交编辑时,你会收到一个错误。然后,您只需重新加载新版本的帖子并重新开始

可能有合并更改的方法,但这是非常棘手的。如果两个编辑的合并导致一组互不相容或没有意义的属性,该怎么办


处理非原子更改的另一种方法(读取当前数据,然后使用PHP等语言在两个单独的请求中处理post更改)是在编辑过程中将记录标记为锁定。但是这还有其他并发性问题。

您能在用户表中使用额外的列吗?如果有很多,而有些用户可能没有,那么您可以有一个与用户表具有1:1关系的用户配置文件表。最后,一个键值字符串对表在过去对我来说工作得很好。序列化思想在某些情况下确实有效,但当然它完全隐藏了数据库级搜索、排序和连接的数据,因此如果可以,应该避免使用。@halfer,键值设计(也称为实体属性值)并不能解决并发问题,比尔:我认为这取决于OP所指的并发问题。我假设,由于他的值数组目前是序列化的,在这样的设计中写入“一”值实际上会写入所有值,并破坏同时添加、删除或更新的其他值。我同意键值设计并不总是最佳的,但是为用户1234添加/更新/删除键“name”应该是原子的,除非其他人在另一个会话中编辑了相同的键。任何
更新
都是原子的,但循环实际上是
选择
读取当前值,将其呈现给用户,让他们编辑它,然后使用
更新
@Bill,true将其发回。Peter,为了解决这个问题(不管你最终如何存储数据),你的表单可以包含一个最近更新的隐藏字段,然后在保存时,如果这与数据库副本不一致,请拒绝编辑并要求用户刷新。这也是我在考虑选项时得出的结论。我确实考虑了一个关键价值商店,但它似乎比它的价值更麻烦。我认为,也许我的第二个想法(以及你在这里的建议)是最好的想法,只需保留上次更新的时间戳,并确保提交的副本与实际的上次更新时间相匹配。我想尝试合并更改,但我想不出一个好方法来对两个数组进行合并,除非每个属性都有自己的“上次更新”值进行比较。