1

我制作了一个非常简单的脚本来遍历我们所有的用户,每次执行的限制为 500。

它执行以下操作:

  1. 选择用户数据
  2. 插入一行
  3. 向用户发送电子邮件
  4. 更新一行
  5. 下一个用户

它按预期工作并成功完成。

但是,当我运行它时,我无法在另一个窗口中使用该网站,因为它只是“加载”,直到该脚本完成执行?

就好像脚本在运行时锁定了用户表,但这不应该发生,因为我们只是使用保存到的数据$result

但是我可以在网站冻结时通过sqlyog查询数据库,所以不能这样吗?会不会只是使用了太多资源?

脚本- 示例

<?
set_time_limit(0);

require '../connect.php';
require '../includes/ses.php';

$i = 1;

$ses = new simpleemailservice();

$result = mysql_query("SELECT id, username, email FROM `user` WHERE thiscol = 0 LIMIT 500");

while($row = mysql_fetch_row($result)){

    mysql_query("INSERT INTO table (data) VALUES (1)");

    $m = new SimpleEmailServiceMessage();

        $m->addTo($row[1]." <".$row[2].">");
        $m->setFrom("Emailer <no-reply@emailer.com>");
        $m->setSubject("Subject");
        $m->setMessageFromString("Email Text", "Email HTML");

    if($ses->sendEmail($m))
        mysql_query("UPDATE `user` SET thiscol = 1 WHERE id = ".$row[0]);

    $i++;
}
?>
4

1 回答 1

2

这种行为听起来像会话锁定。PHP 会话的默认工作方式是锁定会话(以防止两个进程写入会话对象)。这对于典型的短期 PHP 脚本来说通常很好,但是当你有一些长期运行的东西时可能会咬你。

session.auto_start如果您的应用程序根本不使用会话,那么您应该在 php.ini 或 .htaccess 中关闭: http ://www.php.net/manual/en/session.configuration.php#ini.session.auto-start (如果您在那里看不到它,或者它已经关闭,但是您正在使用某种框架,则该框架可能正在为您启动会话;如果是这样,那么转到下一个解决方案比尝试战斗更简单框架。)

如果您在某些页面上使用会话,但不在这个长期运行的进程中,解决方案是在脚本开始时关闭会话,使用session_write_close()

<?
set_time_limit(0);

require '../connect.php';
require '../includes/ses.php';

session_write_close();

$i = 1;
....

再次,框架警告:如果框架正在为您启动会话,则放在session_write_close();包含框架文件之后,而不是之前!(你在评论中提到了这种情况,这就是为什么我把它放在 require 行之后。)

如果您的长时间运行的进程需要使用会话,但只读,则上述方法仍然有效。请参阅https://stackoverflow.com/a/14409902/841830 (如答案所示,如果您需要在长时间运行的过程结束时写入会话,这也是可能的。)

(PS 这已经在评论中得到了回答,但我已经接受了 Wrikken 的提议,将其作为答案发布。是的,谣言是真的:我会为一些代表做任何事情......)

于 2013-10-18T02:01:08.903 回答