2017-07-30 58 views
4

有一个名为function.php的文件,我打电话到我的网站的所有页面require_once。该文件包含超过一百个函数。如何在PHP中处理太多的数据库连接而不增加最大连接数?

我从mysqli_connect(),右max_user_connections错误表明

mysqli_query() expects parameter 1 to be mysqli, boolean given

错误后,当有太多的游客或搜索引擎机器人爬行快。

功能文件是这样的:

<?php 
function db_connect(){ 
    $link=mysqli_connect("host","dbuser","dbpass","dbname"); 
    if (mysqli_connect_errno()) { 
     echo "Failed to connect to MySQL: " . mysqli_connect_error(); 
    } 
    mysqli_query($link,"set names 'utf8'"); 
} 

db_connect(); 

function func_1(){ 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 

function func_2(){ 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 

. 
. 
. 

function func_100(){ 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 
?> 

最后我关闭数据库连接。因为我已经检查了每个用户的最大连接数,我的数据库是50,主机提供商不会改变它(这就足够了,他们说)。

那么,一般如何处理这个问题呢? (简单的PHP或OOP)

+0

我不知道发生了什么问题 - 我怀疑错误是在你没有向我们显示的代码的某个部分 - ,但是你的'db_connect'函数将一个连接分配给一个局部变量,然后永远不会传递出来。这会烧你的地方! –

+0

对不起,我忘了。我在需要的代码中使用“全局$链接”。它通常工作正常,但有时我得到这个错误。 – Rasoul

回答

-1

你这里有多种选择:

首先,您使用的是$链接变量超出范围。您可以使用此代码修复它:

<?php 
$link = null; 
function db_connect(){ 
    global $link; 
    $link=mysqli_connect("host","dbuser","dbpass","dbname"); 
    if (mysqli_connect_errno()) { 
     echo "Failed to connect to MySQL: " . mysqli_connect_error(); 
    } 
    mysqli_query($link,"set names 'utf8'"); 
} 

db_connect(); 

function func_1(){ 
    global $link; 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 

function func_2(){ 
    global $link; 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 

. 
. 
. 

function func_100(){ 
    global $link; 
    $result=mysqli_query($link,"select * from ..."); 
    ... 
} 
?> 

第二:(如O.Jones所建议的)。你只依靠require_once。您可以检查是否连接创建之前坚固,这一点:

if (!$link) db_connect(); 

(对于这种情况,获得该文件之外声明的$链接变量,一个总是叫一个)

三:PHP自动管理连接,并在最后一个字节提供给客户端后销毁。也许,如果你在不再需要的时候用mysqli_close函数自己关闭连接,你可以解决问题。你可以在这里查看关于如何使用这个功能的文档:http://php.net/manual/en/mysqli.close.php

如果问题仍然存在,也许你需要使用持久连接,从你的php到你的数据库的连接较少。您可以通过“p:”(不带引号)来实现这一功能。例如,连接到sql.myserver.com,你需要使用:

$link=mysqli_connect("p:sql.myserver.com","dbuser","dbpass","dbname"); 

你能得到关于与PHP手册中的mysqli此页面上的持久连接的详细信息:http://php.net/manual/en/mysqli.persistconns.php

+0

'global'是一个[糟糕的解决方案](https://stackoverflow.com/documentation/php/194/variables/2496/global-variable-best-practices) – Machavity

+0

为什么是-1?也许全球并不是更好的选择,但至少是没有重做所有代码的解决方案。如果您有更好的选择,请发布它。我可以学习它。但是,对于一个没有建设性的批评者,我不能再学习或解决这个问题。 –

+0

因为你正在传播一种糟糕的代码方式。如果某人在其他地方使用'$ link'会怎么样?你的代码突然停止工作。你还建议一些其他不好的:持续连接。从经验来看,持久性不会在终止时释放,这对于网站来说是一件坏事。这样做实际上会加剧问题,因为PHP仍然会在持久化之上创建**新**连接。 – Machavity

0

你显然在处理每个网页请求的过程中,打开多个到您的MySQL服务器的连接。

在您的代码文件中定义了db_connect()函数之后,即可调用该函数。这可能会导致它被称为比必要的更频繁。每次调用它时,它都会从连接池中消耗稀缺资源。

取而代之,请执行一些操作以确保该函数一次由代码处理每个页面调用。最好将MySQL连接作为处理逻辑的一部分,而不是依靠require_once来完成。确保在完成使用后关闭打开的连接。

当你确定你必须在每个页面打开正在处理最多一个MySQL连接,那么你可能需要减少 PHP文件,你的Web服务器可以同时处理的数量。这可以通过调整Apache Web服务器参数MaxClients和/或MaxRequestsPerChild来完成。另一个流行的Web服务器nginx具有相似的参数。减少此容量不会损害用户,因为Web服务器处理来自队列的页面请求。

+0

他们可以使用类似if(!$ link)的东西来避免创建多个连接,但是如果他们真的只使用require_once,那不是问题。但是,这是一个更好的编码的好点,我增加了我的回应。 –

0

如果由于无效原因导致连接数太多,请修复它。看看连接何时关闭以及如何进行。看看连接的持久性。如果确定这些都没问题,那么你有太多的连接,那么你可能需要在一个支持它的环境中为你的服务器开发一个多线程的独立应用程序,并在那里使用10个持久连接线程。此应用程序将使用一个队列来知道需要从数据库中询问什么,以及在工作线程完成进程,获取结果,将其发送给请求者并继续下一项从队列中。

0

我会变钝的。因为这里没有编码解决方案

因为我已经检查了每个用户对于我的数据库的最大连接数是50,主机提供商不会改变它(这就足够了,他们说)。

我怀疑你是在一些便宜/免费的托管解决方案,他们可以保持廉价/免费,因为他们油门你。 50对于比较流行的个人Wordpress站点(例如每天1000次访问)来说是很好的选择。但是超出这一点很容易。 PHP正在创建超过50个并发连接。这是一个资源问题,你只能通过增加可用连接数来解决它。

由于您当前的主机不会这样做,您需要移动到可以的位置。无论是或者接受你的一些访问者不会得到他们期待的网页。

+0

你是对的,但它不是很便宜的主机(不适合我!!)。我只是为目前的情况寻找最佳解决方案。 – Rasoul

+0

你好@Machavity ...请问,你能解释一下我,为什么你要删除我回答过的编辑问题中的所有“订单”标签? … 有什么不对? ...谢谢 – LoicTheAztec

+0

@LoicTheAztec https://meta.stackoverflow.com/a/324444/2370483 – Machavity

0

使用singleton可以只为$link或全部function.php

0

我想补充的方法getLink您在所有查询中使用呼吁:

function getLink() { 
    static $link; 

    if(! $link) 
     $link = db_onnection() ; 

    return $link; 
} 

,然后在查询:

mysqli_query(getLink(), "SELECT id,..."); 

此外,这是单例模式这是一个变化反模式!