我有一个CMS在多个人登录时失败。我认为问题可能是我没有正确关闭数据库。以下是基本设置:
我有一个名为Mysql的大师班。 __construct()方法如下所示:
class Mysql {
protected $conn;
function __construct() {
if(!$this->conn) $this->conn = New mysqli(SITE_HOSTNAME, SITE_USERNAME, SITE_PASSWORD, SITE_DATABASE);
}
我的所有类都是这个类的后代,所以每当它们被实例化时,它们都会得到自己的连接。
我正在使用预准备语句来防止sql注入。示例方法可能如下所示:
function foo($blog = 0) {
$query = "SELECT catid, catname
FROM category
WHERE blog = ?
ORDER BY catname ASC";
$result = array();
if($stmt = $this->conn->prepare($query)) {
$stmt->bind_param('i', $blog);
$stmt->execute();
$stmt->bind_result($catid, $catname);
while($stmt->fetch()) $result[$catid] = stripslashes($catname);
$stmt->close();
return $result;
}
}
Mysql __destruct()方法如下所示:
function __destruct() {
if($this->conn) $this->conn->close();
}
我的问题是我没有正确关闭我的连接,或者我没有足够的活动连接?
我的提供商说我有30个可用的同时连接。还不够吗?
感谢您的帮助。
答案 0 :(得分:2)
我的所有课程都是这门课程的后代,所以无论什么时候 实例化,他们得到自己的联系。
您执行此操作的方式的问题是,继承Mysql
的任何类的每个实例都打开与Mysql
服务器的连接,该服务器一直存在,直到请求完成,或者变量destructed(除非你手动杀死这些对象,这是在请求的最后)。如果您有30个这样的类实例,那么您已经最大化了连接。
您的类不应该都继承这个代表数据库接口的Mysql
类。
相反,您应该在需要的地方传递此Mysql
类的单个实例。
有两种方法可以有效地完成:
class SomeClass {
protected $db;
public function __construct(Mysql &$db) {
$this->db = $db;
}
public function functionThatNeedsDatabase() {
$this->db->doSomethingWithTheDatabase();
}
}
$db = new Mysql(); //A single instance of Mysql class has been created.
$someClass = new SomeClass($db);
$someClass->functionThatNeedsDatabase();
class SomeClass {
public function functionThatNeedsDatabase(Mysql &$db) {
$db->doSomethingWithTheDatabase();
}
}
$db = new Mysql(); //A single instance
$someClass = new SomeClass();
$someClass->functionThatNeedsDatabase($db);
答案 1 :(得分:1)
你的问题是“我的所有类都是这个类的后代,所以每当它们被实例化时,它们就会得到自己的连接。”在PHP中,脚本结束时会自动关闭连接。你真的只需要每个用户1个连接。您应该创建一个DB类的实例,并将该对象传递给需要使用它的所有类(依赖注入模式)。
30个连接不是很多,但这足以满足大量流量。我会避免使用持久连接。请仔细阅读文档,有很多警告。