如何在PHP中处理太多数据库连接而不增加最大连接数?

时间:2017-07-30 12:09:58

标签: php mysql

有一个名为<input type="text" name="input" id="input"> 的文件,我用public ActionResult Index() { var dbContext = new IdentityDbContext<IdentityUser>("DefaultConnection"); dbContext.Database.CreateIfNotExists(); var userStore = new UserStore<IdentityUser>(dbContext); var userManager = new UserManager<IdentityUser, string>(userStore); var result = userManager.Create(new IdentityUser { Id = Guid.NewGuid().ToString(), UserName = "Test" }); var signInManager = new SignInManager<IdentityUser, string> (userManager, System.Web.HttpContext.Current.GetOwinContext().Authentication); var toSign = userManager.FindByName("Test"); signInManager.SignIn(toSign, true, true); return View(); } 将其调用到我所有网站的页面中。该文件包含100多个函数。

我从function.php及之后发现require_once错误

mysqli_query() expects parameter 1 to be mysqli, boolean given
当访问者太多或搜索引擎机器人快速爬行时显示

错误。

函数文件是这样的:

max_user_connections

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

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

7 个答案:

答案 0 :(得分:0)

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

在代码文件中定义db_connect()函数之后,您可以调用该函数。这可能导致它被频繁调用而不是必要的。每次调用它都会消耗连接池中的稀缺资源。

相反,做一些工作以确保通过处理每个页面的代码最多一次调用该函数。作为处理逻辑的一部分管理MySQL连接比依靠require_once为您完成它更好。确保在使用完毕后关闭打开的连接。

如果您确定每个页面最多只有一个MySQL连接正在处理,那么您可能需要减少您的Web服务器可以同时处理的php文档的数量。这可以通过调整apache Web服务器参数MaxClients和/或MaxRequestsPerChild来完成。另一个流行的Web服务器nginx具有类似的参数。减少此容量不会对用户造成伤害,因为Web服务器处理来自队列的页面请求。

答案 1 :(得分:0)

如果由于无效原因导致连接数太多,请修复它。看看连接何时关闭以及如何关闭。看一下连接的持久性。如果甚至确保这些都没关系,那么您可能希望在支持它的环境中为您的服务器开发多线程独立应用程序,并在那里使用10个持久连接线程。此应用程序将使用队列来了解需要从数据库中询问的内容以及要发回的响应的位置以及工作线程完成进程的时间,获取结果,将其发送给请求者并继续下一个项目从队列中。

答案 2 :(得分:0)

我会直言不讳。由于这个原因,这里没有编码解决方案

  

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

我怀疑你是在一些便宜/免费的托管解决方案,他们可以保持廉价/免费,因为他们扼杀你。例如,50个适用于具有中等流量的个人Wordpress网站(例如每天1000次访问)。但它很容易超过这一点。 PHP正在进行50多个并发连接。这是一个资源问题,您只能通过增加可用连接数来解决它。

由于您当前的主持人不会这样做,您需要转移到可以。无论是那个还是接受一些访问者都没有获得他们期望的网页。

答案 3 :(得分:0)

$link只使用function.php或全部package myserver.pkg1.pkg0; import java.net.*; public class Server implements Runnable { protected boolean isStopped = false; protected static ServerSocket server = null; public static void main(String[] args) { try { server = new ServerSocket(9000); System.out.println("Server is ON and listening for incoming requests..."); Thread t1 = new Thread(new Server()); t1.start(); } catch(Exception e) { System.out.println("Could not open port 9000.\n" + e); } } @Override public void run() { while(!isStopped) { try { Socket client = server.accept(); System.out.println(client.getRemoteSocketAddress() + " has connected."); Thread t2 = new Thread(new Server()); t2.start(); new Thread(new Worker(client)).start(); } catch(Exception e) { System.out.println(e); } } } }

答案 4 :(得分:0)

我会在所有查询调用中添加一个方法getLink

function getLink() {
    static $link;

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

    return $link;
} 

然后在你的查询中:

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

此外,这是单身模式的变体,这是一种反模式!

答案 5 :(得分:0)

这是我在处理偶尔的高流量时发现的解决方案。关键是要检测MySQL客户端有此错误,然后等待重试连接。

它不会像减少所需的连接数或增加连接那样有效,但是在某种程度上,它应该防止错误发生,前提是最终实际上要关闭连接。这会减慢访问者的体验(加载时间会受到影响),但是我希望用户等待更长的时间比收到错误更好。

$sql = @new mysqli($db_host, $db_user, $db_pass, $db_name);
$iSqlAttempt = 1;
//Detect the maximum connection error.
while ($sql->connect_errno == 1040 && $iSqlAttempt < 10) {
  //Sleep 10ms then retry. The time doubles after each attempt.
  usleep(pow(2, $iSqlAttempt)*10000);
  $sql = @new mysqli($db_host, $db_user, $db_pass, $db_name);
  $iSqlAttempt ++;
}
if ($sql->connect_error) {
  die('Connect Error ('.$sql->connect_errno.') '.$sql->connect_error);
}

如果10次尝试/ 10秒后仍无法访问数据库,则它将退回到报告错误的位置,但是希望您的情况没有那样糟糕。

希望有帮助!让我知道是否有任何问题。

答案 6 :(得分:-1)

这里有多个选项:

首先,您使用$ link变量超出范围。您可以使用以下代码修复它:

<?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();

(对于这种情况,获取在此文件之外声明的$ link变量,在一个总是被调用的文件上)

第三: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