PHP旋度计时不匹配

PHP旋度计时不匹配,php,curl,Php,Curl,我正在运行一个php脚本: 查询本地数据库以检索金额 执行curl语句以使用上述数量+x更新外部数据库 再次查询本地数据库,以插入反映已执行curl语句的新行 我遇到的一个问题是curl语句需要2-4秒才能执行,因此我有两个来自同一公司的不同用户同时运行同一个脚本,curl命令的执行时间可能会导致外部数据库中应该更新的内容不匹配。这是因为curl语句尚未从第一个用户返回…因此第二个用户正在处理错误的数字 我不确定这里的最佳选项,但基本上我需要防止同时运行两个或多个curl语句 我考虑在数据库中存

我正在运行一个php脚本:

  • 查询本地数据库以检索金额
  • 执行curl语句以使用上述数量+x更新外部数据库
  • 再次查询本地数据库,以插入反映已执行curl语句的新行
  • 我遇到的一个问题是curl语句需要2-4秒才能执行,因此我有两个来自同一公司的不同用户同时运行同一个脚本,curl命令的执行时间可能会导致外部数据库中应该更新的内容不匹配。这是因为curl语句尚未从第一个用户返回…因此第二个用户正在处理错误的数字

    我不确定这里的最佳选项,但基本上我需要防止同时运行两个或多个curl语句

    我考虑在数据库中存储一个值,该值指示此时正在执行curl语句,并防止任何其他curl语句在其完成之前运行。执行第一个curl语句后,数据库标志将更新,下一个可以运行。如果此字段为“锁定”,则我可以循环代码并休眠(5)秒,然后再次检查标志是否已重置。如果在(3)个循环之后,则自动重置标志(我从未见过卷曲时间超过5秒)并继续处理

    还有其他(更优雅的)方法吗?

    您可以在任意文件中使用。这样,第二个脚本将阻塞,直到它可以获得锁为止

    $lockfile = 'foo.bar';
    $fd = fopen($lockfile, "w");
    if (flock($fd, LOCK_EX)) {
        do_your_stuff();
    }
    else
        die("error"); //should not happen; flock should block until the lock is acquired
    
    fclose($fd);
    
    编辑:

    PHP不是JavaEE,没有实现分布式事务的简单方法。

    您需要的是调用。许多人已经投入了大量的时间和精力来研究这个问题

    这个问题并不像你希望的那么简单。一些论坛引擎(cough-Stackoverflow-cough)也实现了类似的功能,因此它可以按创建(未发布)的顺序显示帖子。这是通过创建一个随机令牌来完成的,最终用户必须使用该令牌来通知服务器它仍然处于活动状态,并且仍在不时处理当前正在编辑/添加的记录。最常见的问题是连接超时和用户超时。通过让客户端定期向服务器发送心跳信号(在web上,这通常是通过发出HTTP请求通知服务器连接仍处于活动状态-打开)来修复连接超时;如果客户端长时间停止发送hearbeats,则认为服务器已超时。同时,客户端还应该知道心跳是否已经到达服务器,并且在连接超时的情况下,应该考虑该做什么。还有一种情况是用户超时,用户只需锁定一条记录并离开计算机很长一段时间。在这种情况下,客户机和服务器都应该知道记录已被锁定,但它已经很长一段时间没有被使用(编辑),因此他们都应该采取行动


    这个问题看起来很简单,可以用一句话来表述,但答案非常复杂,取决于许多因素。

    curl支持使用curl\u multi\u exec()对N个资源进行并行请求。如果您想按顺序进行这些调用(其中有多个curl_*调用)并执行上述语句,则在使用原子操作时不要使用curl_multi

    如果您访问的更新的数据库记录不能(或不应该)被超过1个用户同时访问,那么您应该考虑从数据库服务器可用的锁定/事务。< /P>


    如你所说,使用带有列标记记录为“锁定”的伪事务机制可能会对你有所帮助,但我不能确定(有一种使用时间戳的伪事务方法,你可以通过谷歌搜索获得更多信息)。

    不幸的是,这不起作用,由于锁必须在每个公司的基础上发生-只要每个公司在任何时候只有一个锁,就可以运行并发的curl操作。@JonoB:为每个公司使用一个唯一的文件,如md5($companyName)。@Tom OK,这是有道理的,但是每次将新公司加载到系统时,我仍然必须创建一个新文件。为什么这种基于文件的方法比在数据库中创建布尔值更受欢迎?@JonoB您描述的数据库过程只有在使用可序列化隔离级别时才有效。据我所知,您从未使用当前数量更新本地数据库(第3步说“插入新行”)。因此,本地数据库中的当前数据量总是相同的,不考虑有多少人同时运行curl。这里需要更多的细节,但这听起来像是一个基本的锁定问题。谷歌“悲观锁”和“乐观锁”。这也将有助于从等式中删除curl,并用一个真正的web服务替换它。实际上,在步骤1中计算的金额是基于之前在步骤3中插入的所有记录的总和。