如何防止php中两个独立的ajax调用修改同一个数据库

how to prevent two separate ajax calls in php from modifying the same database

本文关键字:ajax 独立 调用 修改 数据库 同一个 两个 php 何防止      更新时间:2023-09-26

我得到了一个javascript客户端,它有时会在几毫秒内向(php)服务器发送两个ajax请求。(这是一个javascript错误,我无法从客户端控制,只能从服务器端控制)。

第一个请求检查数据库中是否已经存在凭证(给定几个参数..即客户id等)。。如果凭证已经存在,它只会重新使用凭证并更新其值;如果不存在,它会从头开始创建一个新的凭证。

问题是,在它检查完凭证是否存在之前。。第二个请求进入并检查代金券是否也存在。。此时,第一个还没有创建代金券。。

长话短说。。我们最后得到两张重复的代金券。。(数据库没有限制凭证名称的唯一性。我也无法控制数据库)。。

那么,如何防止第二个ajax请求做任何事情,直到第一个完成它的任务?

请记住,这两个请求是两个不同的线程。。因此,如果我生成任何$isVoucherCreateonProgress变量,它将是无用的,因为第二个调用将完全忽略它。

想法?

如果两个ajax请求来自同一个客户端,则在服务器端创建一个类似锁的系统,因此,如果有人检查了代金券的存在,则设置一个会话变量,直到它完成它必须做的事情。因此,当第二行出现时,它首先检查会话,如果(其他人正在使用代金券)稍后通过消息检查完成,因此,在客户端,当消息被拒绝时,您可以简单地延迟1秒发送,以确保没有人"工作"。

希望这能有所帮助。

或者,您可以看到这个问题,以便在php中生成互斥:php互斥(mutex)

就我个人而言,我会想到一个非常简单的方法。在您的服务器上,您必须有一个创建代金券的过程。保留一个全局数组,在创建凭证之前,将数组的索引设置为id,就像key=>Value一样,其中key可能是凭证的id,Value可能是"正在创建"之类的状态。创建凭证后,您可以使用凭证的id作为关键字删除条目。

现在,每次在创建凭证之前,只需从密钥的全局数组中检查是否已经存在,如果是并且Value="正在创建",那么实际上,您实际上正在创建凭证,因此您退出

希望它能有所帮助,:-)

使用事务。如果你真的不能接触数据库(甚至不能做出自己的声明),你可以使用STM或类似的东西。锁也不会太难,但无论哪种方式都需要您的应用程序持续运行。您可以使用phpdaemon之类的软件运行服务器,并将特定路径转发到该服务器,以获得该连续性。

我知道您在数据库的一个表中创建了一个新行。

应该添加一个唯一性约束,这样就不能添加两次。您是否可能必须创建多个代金券?你能提供更多信息吗?

关于更新,您应该在行中添加一个"版本"字段。客户端需要具有正确的版本号才能更新行。因此,它避免了不需要的并发更新问题。这是ORM的最佳实践,您可以查看此项以寻找"乐观更新"。


由于您无法控制数据库,请在服务器中创建一个请求缓存(即静态对象),并在缓存中创建/更新一行(如果需要,则与此客户+其他参数有关)(例如http://www.php.net/manual/en/book.memcache.php)。您的缓存应该在一段时间内自行清理(我想php中有缓存解决方案)。


另一个想法(很难看,但因为你的解决方案似乎太有限了):放慢速度。等待足够的时间以确保没有其他人(你需要一个循环,如果需要的话,它会检查并撤消——随机收敛)。

您可以在ajax请求启动时设置一个标志(用JavaScript)-检查是否已设置,然后返回,也可以将ajax请求更改为同步。