【问题标题】:Php long query executionphp长查询执行
【发布时间】:2012-12-21 23:55:22
【问题描述】:

我运行了一个大约需要 20 分钟才能完成的过程,我只是想知道 PHP 是否可以在该过程完成之前保持连接处于活动状态。

需要说明的是,这个页面会有一个按钮,当你按下它时会调用一个php页面来运行一个sql查询,在主页面我只是等待Http请求完成发送一条成功消息。

【问题讨论】:

  • 你为什么不试试呢。不应该超过 20 分钟;)
  • 后台操作怎么这么重?
  • @byoigres 您可以为任何给定脚本设置一个新的max_execution_time。但你的首要任务应该是问为什么这个查询需要这么长时间
  • 您应该将该过程与 HTTP 请求周期分离。期望您的用户能够可靠地让浏览器保持打开并连接 20 分钟,这始终是一种黑客行为。
  • 如果你从网络浏览器运行它,那么网络服务器也会有一个超时值,可能不超过 5 分钟......但是用户等待超过几秒钟浏览器响应几乎肯定会变得不耐烦

标签: php


【解决方案1】:

对于设置为占用一些时间的查询,您应该将一些自动化请求移动到组合中,如果您可以访问 linux 服务器,最好是 cronjobs。

使用 cronjobs,您可以在数据库中为特定值创建条目,链接到用户。如果挂起的查询已完成,cronjob 将启动,每 5 分钟执行一次查询。这将最大限度地减少用户需要坐在页面上直到完成的事实。因为您应该知道,用户离开活动页面的那一秒;所有活动的连接、查询等都将停止。

脚本完成后,在最后制作一条自定义消息发送给用户,让他们知道他们的过程已经完成。

您还应该知道,PHP 会从第 1 行到最后执行脚本;因此,例如,如果您的挂起在第 40 行;该脚本将位于该行,直到查询完成然后继续处理。

编辑:这只是为了给你指出我要达到的方向,而不应该像你看到的那样使用它。这只是一个标记示例

<?php
    if (isset($_POST['ButtonToExecute']))
    {
        // Query to update a table in your database which an external PHP script will work with
        // Example Table Structure:
        /*
            Username
            State

        */
        if ($state == 0)
        {
            // Then update state to 1 with username to the username for the query to take place on

        }
        else
        {
            // Warn user that their process will take longer to complete as their already is an active query in process
            // but add them to a secondry pipeline which will be picked up on the next cronjob interval
        }
    }
?>

在你的 cronjob 中,可能有:

<?php

if ($state=='1')
{
    // Execute your script
    // After query execution update state to 2

    // if state == 2 then insert custom message/email to send
}

?>

编辑你的 crontab:

yourpreferrededitor /etc/crontab

^ yourpreferrededitor 表示您的文本编辑器,无论是 nano 还是其他。

还有你的 cronjob 行:

* * * * *  root /usr/bin/php /var/www/cron.php 

^ 这是从我每天每一分钟都在不断运行的当前 cronjob 中获取的

Cronjob 将使用户能够离开页面,因为正如我上面提到的,用户离开脚本的那一刻......所有正在进行的进程都会停止。 cronjob 将持续运行,无需用户交互(除了他们发出初始请求)

【讨论】:

  • 好点。但是许多客户想要一种在他们选择的时间触发工作的方法。因此,我们通常必须以允许将查询作为 cronjob 或根据用户请求运行的方式来实现。如果他们只使用命令行,Live 会更容易;)
  • 用户请求可以通过按下按钮发出,然后锁定下一个 cronjob 在他们的名字中;我正在研究标记脚本。仅用于示例目的;并且应该用作参考而不是用于生产
  • @OliverA。你能浏览一下我的编辑,并告诉我是否应该有一个更深入的例子吗?或者得到 jist (我知道你不是 OP,但其他 cmets 会对 OP 有益)
  • @DarylGill 您可以更深入地了解为此目的使用 cronjobs;为什么有一个单独的脚本来运行连接?为什么他们应该是“管道”中的请求,运行标准用户无法访问的 PHP 脚本的主要目的是什么,只有 cronjob?
  • @user1902584 由于用户没有提供他们尝试过的代码,我只给了他们一个用法示例和他们应该做什么的粗略概述——如果他们决定接受cronjob 解决方案,如果他们没有为我提供任何工作,我不会为他们完成整个工作;
【解决方案2】:

如果您设置超时限制并忽略用户中止,您可以在普通 php 脚本中执行此操作,但这是一个坏主意,因为如果脚本有效,您的用户将没有任何反馈。

在我工作的公司,我们遇到了同样的问题 我们做了什么:

  1. 在单独的脚本中运行查询。
  2. 无需等待结果即可启动脚本
  3. 将查询拆分为多个部分(使用限制和偏移)
  4. 让查询脚本将消息写入临时文件
  5. 实现一个状态屏幕,通过 ajax 从日志中获取当前状态

顺便说一句,所有智者都会问为什么需要这么长时间:

如果您必须处理具有数百万个节点的树但构建它可能需要数小时,则使用 transitive hull 可以大大加快您的应用程序的速度。

【讨论】:

    【解决方案3】:

    你可以试试:

    set_time_limit(0);
    

    你可能想看看Set Time Limit

    【讨论】:

      【解决方案4】:

      在您的 PHP ini 中,您可以设置脚本的最大执行时间,但是您永远不希望用户在页面加载屏幕上停留那么久。

      我可以建议的一件事是将您的最大执行时间增加到大约 30 分钟,然后在页面已经呈现后在 javascript 中调用它,这样用户就不会被留在黑暗中不知道什么脚本正在执行。

      【讨论】:

        猜你喜欢
        • 2016-09-13
        • 1970-01-01
        • 1970-01-01
        • 2019-04-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多