0

可能重复:
如何实现应该在 php 中的线程中完成的任务

通常在 PHP 中运行 PDO 查询时,它会等待数据库结果。有没有办法避免这种情况?

我需要我的脚本快速回复,但运行的 SQL 可能需要一些时间才能运行。

例子:

<?php
$pdo = new PDO('bla bla');

// This takes up to 1 second, but I need the script to reply within a few ms
$pdo->exec('UPDATE large_table SET foo = \'bar\' WHERE id = 42');
die('ok');

这是可行的吗?

4

3 回答 3

2

对于INSERT查询,您可以使用INSERT DELAYED手动)。这些查询将被放入工作队列并立即返回。缺点是您没有关于查询是否成功执行的任何反馈。

然而,由于不明原因,没有UPDATE DELAYED...

于 2013-01-23T21:36:08.523 回答
1

常见的方法是先渲染输出,然后使用刷新输出到客户端flush(),然后执行耗时查询。你也应该知道ignore_user_abort(). 尽管与客户端的连接可能已经结束,但此函数使 PHP 保持运行。(例如用户关闭浏览器)

我准备了两个脚本来说明这一点。首先是slow.php提前刷新输出,然后开始一项耗时的任务。第二个是get.php使用 libcurl 接收页面。如果您对其进行测试,get.php 将几乎立即返回,而 slow.php 仍在运行。我还用当前的 Mozilla 测试了慢速 php。

慢.php:

// The example will not work unless ob_end_clean() is called
// on top. Strange behaviour! Would like to know a reason
ob_end_clean();

// disable all content encoding as we won't
// be able to calculate the content-length if its enabled
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
header("Content-Encoding: none");


// Tell client that he should close the connection
header("Connection: close");

// keep the script running even if the CLIENT closes the connection
ignore_user_abort(); 

// using ob* functions its easy to content the content-length later
ob_start();

// do your output
echo 'hello world', PHP_EOL;


// get the content length
$size = ob_get_length();
header("Content-Length: $size");

// clear ob* buffers
for ($i = 0; $i < ob_get_level(); $i++) {
    ob_end_flush();
}
flush(); // clear php internal output buffer

// start a time consuming task
sleep(3);

获取.php

// simplest curl example
$url = 'http://localhost/slow.php';

$ch = curl_init($url);
$fp = fopen("example_homepage.txt", "w");

curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);

curl_exec($ch);
curl_close($ch);
fclose($fp);
于 2013-01-23T21:28:12.410 回答
0

在您进行更新时,通过 AJAX 调用您的更新脚本,向您的用户显示一个加载器。

如果您真的不需要在页面加载时输出中的查询结果,这是唯一的方法。

于 2013-01-23T21:26:20.430 回答