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

时间:2012-03-26 18:51:12

标签: php javascript ajax database multithreading

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

第一个请求检查dbase中是否已存在凭证(给定一些参数...即cust id等)..如果凭证已经存在,它只是重新使用凭证并且更新是值,如果它没有,它从零开始创建一个新的。

问题是在它完成检查凭证是否存在之前......第二个请求进来并检查凭证是否存在..那时第一个还没有创建凭证..

这么长的故事简短..我们最终得到了2张重复凭证..(并且dbase不会将凭证名称限制为唯一。我也无法控制dbase。)

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

请记住,这两个请求是两个不同的线程..所以如果我创建任何$ isVoucherCreationInProgress变量,它将是无用的,因为第二个调用将完全无视它。

想法?

5 个答案:

答案 0 :(得分:2)

如果2个ajax请求来自同一个客户端,则在服务器端创建一个类似锁的系统,因此如果有人检查了凭证存在,请设置一个会话变量,直到它完成它必须执行的操作为止。因此,当第二行出现时,它首先检查会话以及是否(其他人正在使用凭证)以后通过消息检查完成它,所以在客户端,当它带有拒绝消息时,您可以简单地发送它1第二次延迟,确保没人在“工作”。

希望这有帮助。

或者你可以看到这个问题,以便在php中创建一个互斥:PHP mutual exclusion (mutex)

答案 1 :(得分:1)

就个人而言,我会想到一个非常简单的方法。在您的服务器上,您必须具有创建凭证的过程。保持一个全局数组,就在创建凭证之前,将数组的索引设置为id,就像key =>值,其中key可以是凭证的id,Value可以是诸如“创建”的状态。创建凭证后,您可以使用凭证的ID作为密钥删除条目。

现在,每次创建凭证之前,只需从已存在的密钥的全局数组中检查,如果是和Value =“正在创建”,那么实际上,您实际上是在创建凭证,因此您退出< / p>

希望它有所帮助,: - )

答案 2 :(得分:1)

使用交易。如果你真的无法触摸数据库(甚至没有自己的语句),你可以使用STM等。锁也不会太难,但无论哪种方式都要求您的应用程序连续运行。您可以使用像phpdaemon这样的软件运行服务器并转发到该服务器的特定路径,以获得该连续性。

答案 3 :(得分:1)

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

您应该添加一个unicity约束,以便您不能添加两次。您是否可能需要创建多个优惠券?你能提供更多信息吗?

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


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


另一个想法(丑陋但因为看起来你的解决方案似乎有限):只是让它变慢。等待足够的时间以确保没有其他人(如果需要,您将需要一个检查和撤消的循环 - 随机收敛)。

答案 4 :(得分:0)

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