0

这是一个管理轮播广告的 php 文件,该广告会导致严重的服务器性能问题并导致站点上的“连接过多”sql 错误。这是php脚本。谁能给我一些关于如何纠正这个问题的见解,因为我是 php 的新手。

        <?

require("../../admin/lib/config.php");
// connect to database

mysql_pconnect(DB_HOST,DB_USER,DB_PASS);
mysql_select_db(DB_NAME);

$i = 1;
function grab()
{
    $getBanner = mysql_query("SELECT * FROM sponsor WHERE active='Y' AND ID != 999 AND bannerRotation = '0' ORDER BY RAND() LIMIT 1");
    $banner = mysql_fetch_array($getBanner);
    if ($banner['ID'] == ''){
        mysql_query("UPDATE sponsor SET bannerRotation = '0'");
    }   
    if (file_exists(AD_PATH . $banner['ID'] . ".jpg")){
        $hasAd = 1;
    }
    if (file_exists(BANNER_PATH . $banner['ID'] . ".jpg")){
        return "$banner[ID],$hasAd";
    } else {
        return 0;
    }
}

while ($i <= 3){
    $banner = grab();
    if ($banner != 0){
        $banner = explode(",",$banner);
        mysql_query("UPDATE sponsor SET bannerView = bannerView + 1 WHERE ID='$banner[0]'");
        mysql_query("UPDATE sponsor SET bannerRotation = '1' WHERE ID = '$banner[0]'");
        echo "banner$i=$banner[0]&hasAd$i=$banner[1]&";
        $i++;
    }
}

?>
4

3 回答 3

2

我看不到mysqli

问题是mysql_pconnect()打开到数据库的持久连接并且在执行结束时没有关闭,并且由于您没有在任何地方调用 mysql_close() 连接永远不会关闭。

全部在手册中:http: //php.net/manual/en/function.mysql-pconnect.php

于 2012-10-27T17:12:35.723 回答
1

好吧,对您的客户来说,好消息是之前的开发人员放弃了该项目。如果他继续努力,他只会造成更大的伤害。

  • 这个脚本使用的是 ext/mysql,而不是 ext/mysqli。最好使用 mysqli 或 PDO_mysql,因为ext/mysql 已弃用

  • 建议使用完整的 PHP 开放标签语法 ​​( <?php),而不是短标签语法 ​​( <?)。原因是并非每个 PHP 环境都支持使用短标签,如果您将代码部署到这样的环境中,任何浏览该页面的人都可以查看您的代码。

  • 此脚本不进行错误检查。在尝试连接到数据库或提交查询后,您应该始终检查错误。

  • 众所周知,使用ORDER BY RAND() LIMIT 1从数据库中选择随机行的方法效率低下,并且无法优化。随着表增长到多于微不足道的行数,此查询很可能成为您的瓶颈。请参阅我过去关于优化 ORDER BY RAND 查询的一些答案,或Jan Kneschke关于选择随机行的精彩博客。

  • 即使您无法使用ORDER BY RAND(),也无需调用 3 次即可获得三个不同的随机赞助商。只需使用ORDER BY RAND() LIMIT 3. 然后,您不需要针对 bannerRotation 进行复杂且容易出错的更新,以确保您获得以前未选择的赞助商。

  • UsingSELECT *获取所有列,即使此函数不需要它们。

  • 如果赞助商不符合随机选择的条件,即如果它有 active!='Y' 或者如果它的 ID=999,那么我会将其移至不同的表。这将简化您的查询,并使赞助商表更小,查询更快。

  • grab() 函数中的UPDATE没有WHERE子句,因此它适用于赞助商表中的所有行。我不相信这是故意的。我认为它应该只适用于单行WHERE ID=$banner['ID']

  • UPDATE此代码针对同一张表的同一行有两个连续的语句。将这些组合成一个UPDATE修改两列的语句。

  • grab() 函数将值附加在一起,用逗号分隔,然后在返回后立即将该字符串分解为一个数组。好像程序员不知道一个函数可以返回一个数组。

  • $i++条件块放入内部可以使此代码在无限循环中运行。这意味着这个脚本可以永远运行。一旦其中几十个同时运行,您将用完连接。

  • 此代码不使用缓存。任何提供广告横幅的脚本都必须快速,并且对数据库进行多次更新是不够快的。您需要使用一些内存缓存进行读取和写入。一个流行的选择是memcached

为什么这个客户如此不熟练地编写自己的广告横幅服务器?只需使用Google DFP 标准版

于 2012-10-27T18:01:27.507 回答
0

哎呀!

grab()正在从循环中调用,但未参数化。似乎也没有任何理由重复调用它。

200% 的加速很容易实现。

于 2012-10-27T17:10:56.943 回答