PHP foreach用户脚本似乎使apache挂起

时间:2013-10-17 23:40:00

标签: php mysql

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

它执行以下操作:

  1. 选择用户数据
  2. 插入行
  3. 向用户发送电子邮件
  4. 更新一行
  5. 下一位用户
  6. 按预期工作并成功完成。

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

    就好像脚本在运行时锁定用户表但这不应该发生,因为我们只是使用保存到$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++;
    }
    ?>
    

1 个答案:

答案 0 :(得分:2)

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

如果您的应用程序根本没有使用会话,那么您应该关闭php.ini中的session.auto_start或.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();,而不是之前! (你在评论中提到过这种情况,这就是为什么我把它放在需求行之后。)

如果长时间运行的进程需要使用会话,但只读,上面的代码仍然有效。见https://stackoverflow.com/a/14409902/841830 (正如答案所示,如果你需要在长时间运行的过程结束时写入会话,那也是可能的。)

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