【问题标题】:Database Error: [mysqli.mysqli]: User already has more than 'max_user_connections' active connections数据库错误:[mysqli.mysqli]:用户已经有超过 'max_user_connections' 的活动连接
【发布时间】:2010-10-21 02:53:37
【问题描述】:

我有一个每天只有大约 100 人访问的网站,但是当我以用户身份登录时收到以下错误消息:

Warning: mysqli::mysqli() [mysqli.mysqli]: (42000/1203): User mexautos_Juan already has more than 'max_user_connections' active connections in /home/mexautos/public_html/kiubbo/data/model.php on line 26

Warning: mysqli::query() [mysqli.query]: Couldn't fetch mysqli in /home/mexautos/public_html/kiubbo/data/model.php on line 87
Query failed 

我刷新了几次页面,现在一切正常,但由于我没有那么多用户,我怀疑错误在我的代码中,我应该在哪里查找它?

谢谢

编辑:这是模型文件:

<?php
/* 

    Model is the base class from which the other
    model classes will be derived. It offers basic
    functionality to access databases

*/ 
require_once($_SERVER['DOCUMENT_ROOT'].'/config.php'); 
require_once(SITE_ROOT.'includes/exceptions.php'); 

class Model {

    private $created;
    private $modified;

    static function getConnection()
    {
        /* 

            Connect to the database and return a
            connection or null on failure

        */

        $db = new mysqli (DB_HOST, DB_USER, DB_PASS, DB_NAME);
        if(!$db) {
            echo mysql_error();
            throw new Exception('Could not connect to database', EX_NO_DATABASE_CONNECTION);
        }

        return $db;

    }

    static function execSQL($query)
    {
    /*
            Execute a SQL query on the database
            passing the tablename and the sql query.
            Returns the resultset
    */


        $db = null;
        $results = null;
        //echo "query is $query";

        try
        {
            $db = Model::getConnection();
            $results = $db->query($query);
            if(!$results) {
                throw new Exception('Query failed', EX_QUERY_FAILED );
            }
        }
        catch(Exception $e)
        {
            /*  errors are handled higher in the
                    object hierarchy
            */

            throw $e;
        }

        Model::closeConnection($db);

        return $results;
    }

    static function execSQl2($query)
    {
    /*
            Execute a SQL query on the database
            passing the tablename and the sql query.
            Returns the LAST_INSERT_ID
    */


        $db = null;
        $lastid = null;
        //echo "query is $query";

        try
        {
            $db = Model::getConnection();
            $results = $db->query($query);
            if(!$results) {
                throw new Exception('Query failed', EX_QUERY_FAILED );
            }
            $lastid = $db->insert_id;
        }
        catch(Exception $e)
        {
            /*  errors are handled higher in the
                    object hierarchy
            */

            throw $e;
        }

        Model::closeConnection($db);

        return $lastid;
    }

    function delete($table, $id, $conditions = '')
    {
        $query = "delete from $table where id = $id";
        try
        {
            $db = Model::getConnection();
            $results = Model::execSQL($query);
            if(!$results){
                throw new Exception('Could not delete this object', EX_DELETE_ERROR);
            }
            return $results->num_rows;
        }

        catch(Exception $e)
        {
            throw $e;
        }
    }

    static function closeConnection($db)
    {
        $db->close();
    }

    function getCreated()
    {
        return $this->created;
    }

    function setCreated($value)
    {
        $this->created = $value;
    }

    function getModified()
    {
        return $this->modified;
    }

    function setModified($value)
    {
        $this->modified = $value;
    }



}

?>

【问题讨论】:

  • 谢谢,那我基本上应该和$db一样吗?创建另一个函数: $results->close(); ?
  • 老实说,我不确定。我删除了我的评论,因为这有点超出我的深度。但是,如果您查看 mysqli 的文档,您会注意到它强烈暗示查询结果集是到数据库的缓冲连接。虽然 $db->close() 似乎会结束连接,但查询文档表明它正在使用数据库连接来检索结果。
  • 谢谢,我会调查的。

标签: php mysql database mysqli


【解决方案1】:

在您的网站上打开数据库连接的每次点击都使用相同的数据库用户名和密码。您的数据库设置限制了每个用户的连接数,而您正在超过该最大值。

查看此 MySQL 手册页:http://dev.mysql.com/doc/refman/5.0/en/user-resources.html

您的模型类不是那么好,因为它似乎在每个单独的查询中打开和关闭数据库连接。这是对资源的非常糟糕的使用,因为打开和关闭连接的成本很高。我会在您的模型对象上编写一个名为 $db->close() 的析构函数,并更改 getConnection() 以打开一次连接,然后每次都返回它。这意味着将您的模型类转换为非静态用法,但在数据库上这样做会更容易。

无论如何,在您的班级正在执行所有连接和断开连接时,MySQL 可能会备份连接,并且在您达到最大用户限制之前它们没有足够快地清除。

【讨论】:

    【解决方案2】:

    查看处理数据库连接的代码。你在用游泳池吗?您在使用其中一种 PHP 数据库抽象框架吗?

    您是否在每个数据库访问中处理连接?如果是这样,您正在寻找没有明确释放/关闭数据库连接的代码。 (如果你这样做,我建议看这样的文章:http://www.devshed.com/c/a/PHP/Database-Abstraction-With-PHP/

    【讨论】:

      【解决方案3】:

      这应该可以解决您的问题,但我没有测试它。区别:如果第一次调用getConnection(),则会建立并存储连接。其余时间,使用已经建立的连接。

      我删除了 closeConnection 中的操作,因为这会使第一次更改无用。尽管从 execSQL 中删除 closeConnection 调用会更好。

      通常(据我所知),数据库连接会在脚本终止时自动关闭(只要 mysqli 不支持持久性)。但最好在所有数据库内容完成后手动调用(工作)closeConnection。

      <?php
      class Model {
      
          private $created;
          private $modified;
      
          private static $db = false;
      
          static function getConnection()
          {
              /* 
      
                  Connect to the database and return a
                  connection or null on failure
      
              */
      
      
              if (self::$db === false) {
                  self::$db = new mysqli (DB_HOST, DB_USER, DB_PASS, DB_NAME);
              }
      
              if(!self::$db) {
                  echo mysql_error();
                  throw new Exception('Could not connect to database', EX_NO_DATABASE_CONNECTION);
              }
      
              return self::$db;
          }
      
          static function closeConnection()
          {
              // self::$db->close();
          }
      
          // moar functions (...)
      }
      
      ?>
      

      而且...我建议使用现有的数据库访问抽象层来避免将来出现此类问题。

      【讨论】:

        【解决方案4】:

        这里有两个问题;一个加剧另一个。

        @zombat 发现了更大的问题:您不需要为每个查询连接和断开连接。尽管 MySQL 具有快速的设置和拆卸周期,但它会浪费其他资源。在代码的设置步骤中打开一次连接,然后为每个查询重复使用连接,直到页面结束,这样更有意义。我建议为 mysqli 对象使用实例变量。

        (如果您有一个结构,其中有多个数据库并且哪个依赖于对象,那么您需要增强您的数据库处理程序以跟踪它打开了哪些数据库连接,以便它只打开它需要的那些。但是这是一个更高级的主题,大多数人不需要这样做。)

        这里使用的“其他资源”是 MySQL 连接。如果 mysqli 正在创建持久连接,它实际上不会关闭与 MySQL 的连接(事实上,它还应该重新使用连接,这样你甚至不会遇到这个问题,但我离题了)。 MySQL 超时此类连接的默认值为几个小时,因此您可能会遇到该限制。如果您在SHOW PROCESSLIST 中看到数百个“休眠”线程,那么这就是正在发生的事情。要更改的参数是wait_timeoutmax_connections 也可能太低了。

        但我建议您先修复数据库处理程序。

        【讨论】:

          猜你喜欢
          • 2012-07-01
          • 2014-06-14
          • 2011-05-04
          • 2017-12-21
          • 1970-01-01
          • 1970-01-01
          • 2014-05-20
          • 2016-08-01
          相关资源
          最近更新 更多