首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >过多的sql连接错误:由于长轮询

问过多的sql连接错误:由于长轮询
EN

Stack Overflow用户
提问于 2014-01-24 08:21:20
回答 1查看 1.1K关注 0票数 0

我设计了一个编码平台,就像Spoj和Codeforce一样,将在我的学院局域网上组织竞赛。

我在那里使用了长轮询,以便通过JavaScript警报消息向所有用户广播来自Admin的任何通知。当论坛上发布任何内容时,管理员也会收到通知。

但是,只有16个用户(包括1管理员)访问该站点,服务器显示的是too many sql connections。我重新启动了我的笔记本电脑(服务器),它继续了一段时间,然后又崩溃了;给出了和以前一样的错误信息。

当我删除这两个长投票过程时,一切都顺利地进行着。

用于长轮询的服务器端代码:

代码语言:javascript
复制
include 'dbconnect.php';

$old_ann_id = $_GET['old_ann_id']; 
$resultann = mysqli_query($con,"SELECT cmntid FROM announcements ORDER BY cmntid DESC       LIMIT 1");

while($rowann = mysqli_fetch_array($resultann)){
    $last_ann_id = $rowann['cmntid']; 
}

while($last_ann_id <= $old_ann_id){
    usleep(10000000);
    clearstatcache();

    $resultann = mysqli_query($con,"SELECT cmntid FROM announcements ORDER BY cmntid DESC LIMIT 1");
    while($rowann = mysqli_fetch_array($resultann)){
        $last_ann_id = $rowann['cmntid']; 
    }
}

$response = array();
$response['msg'] = 'new';
$response['old_ann_id'] = $last_ann_id;
$resultann = mysqli_query($con, "Select announcements from announcements where    cmntid = $last_ann_id");
while($rowann = mysqli_fetch_array($resultann)){
     $response['announcement'] = $rowann['announcements'];
}

echo json_encode($response);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-27 09:20:15

定义了最大连接。假设默认为100或151个连接,这取决于MySQL的版本。您可以在phpmyadmin中的“服务器变量和设置”中看到值(或者直接执行*显示变量,如"max_connections";* )。

如果将其设置为非常低的值(例如10),并且您有(比方说)15个用户,那么您将很快达到极限。您将为每个长轮询脚本提供自己的连接,并且该连接可能处于打开状态,直到该长轮询脚本结束。每次检查数据库后,脚本可能会断开连接,然后在下次检查时重新连接(也就是说,如果您的长轮询脚本每5秒检查一次数据库,您可能有4.5秒以上的时间,当前有到数据库的连接,但没有使用连接)。

但是,您可以拥有更多的连接,但是如果每个用户多次触发ajax轮询,每个用户都可以有几个同时进行的连接。这可能很容易用javascript中的一个小错误来完成。

更糟糕的是,如果使用的是持久连接,则在用户离开调用长轮询脚本的页面后,可能会打开连接。

编辑-基于您的脚本更新。

注意:我不确定您的dbconnect.php包括做什么。我可能很容易在其中调用一个连接/断开函数,但我只是将它作为使用mysqlu_close和mysqli_connect函数的代码放在了这个示例代码中。

代码语言:javascript
复制
<?php
include 'dbconnect.php';
$old_ann_id = $_GET['old_ann_id']; 
$resultann = mysqli_query($con,"SELECT MAX(cmntid) FROM announcements");
if($rowann = mysqli_fetch_array($resultann))
{
    $last_ann_id = $rowann['cmntid']; 
}
$timeout = 0;
while($last_ann_id <=$old_ann_id and $timeout < 6)
{
    $timeout++;
    mysqli_close($con);
    usleep(10000000);
    clearstatcache();
    $con = mysqli_connect("myhost","myuser","mypassw","mybd");
    $resultann = mysqli_query($con,"SELECT MAX(cmntid) FROM announcements");
    if($rowann = mysqli_fetch_array($resultann))
    {
        $last_ann_id = $rowann['cmntid']; 
    }
}
if ($last_ann_id >$old_ann_id)
{
    $response = array();
    $response['msg'] = 'new';
    $response['old_ann_id'] = $last_ann_id;
    $resultann=mysqli_query($con,"SELECT cmntid, announcements FROM announcements WHERE    cmntid>$old_ann_id ORDER BY cmntid");
    while($rowann = mysqli_fetch_array($resultann))
    {
         $response['announcement'][]=$rowann['announcements'];
         $response['old_ann_id'] = $rowann['cmntid'];
    }
    mysqli_close($con);
    echo json_encode($response);
}
else
{
    echo "No annoucements - resubmit";
}
?>

我在主循环中增加了一个计数。但是一旦它执行了6次,它就会退出循环,是否找到任何东西。这样,即使有人离开页面,脚本也只会运行一段很短的时间(最多一分钟)。您必须修改javascript才能捕捉到这一点,并重新提交ajax调用。

另外,我已经将响应中的声明更改为数组。这样,如果在脚本运行时有几个公告,所有这些都会被带回。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21327714

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档