【问题标题】:How should I handle a "too many connections" issue with mysql?我应该如何处理 mysql 的“连接太多”问题?
【发布时间】:2014-09-07 15:01:20
【问题描述】:

我正在工作的网络初创公司的并发网络用户数量从平时的 5000 人激增到周末的 10000 人。这个星期六的流量如此之高,以至于我们开始间歇性地收到“连接过多”错误。我们的 CTO 通过简单地增加 tatabase 服务器上的 max_connections 值解决了这个问题。我想知道在这里使用一个持久连接是否是更好的解决方案?

即而不是使用:

$db = new mysqli('db_server_ip', 'db_user', 'db_user_pass', 'db_name');

我们使用:

$db = new mysqli('p:db_server_ip', 'db_user', 'db_user_pass', 'db_name');

我们已经在使用多个 MySQL 服务器以及多个 Web 服务器 (Apache + mod_php)。

【问题讨论】:

  • 我们确实关闭了连接!我说的是并发用户过多时的问题。
  • 您需要所有这些连接吗?你能减少服务器上的负载吗?通过使用 HTML 或片段缓存?
  • 也许您需要调整 MySQL 服务器和/或查询?此外,每天 10K 连接并不是很多——大约每 8 秒就有一个。 Web 服务器上的峰值请求/秒是多少(假设它们捆绑在一起)?
  • 10k 并发用户。每日用户约为 50 万。
  • 啊,对了,错过了一点!正如我上面建议的那样,有什么机会可以减少连接数?

标签: php mysql mysqli


【解决方案1】:

您应该在多个 Web 请求之间共享数据库连接。应用服务器上运行的每个进程都应该有一个自己的 mysql 连接,只要该进程正在运行,该连接就会保持打开状态,并为每个传入的 Web 请求重用。

【讨论】:

  • 这个建议有一些危害。如果您的应用程序设置任何选项或对事务进行任何操作,您必须记住,对于 MySQL,您的新进程没有任何不同。如果需要,请使用持久连接,但如果不需要,请不要使用。
  • 我的方法是以可以重用数据库连接的方式编写代码。创建一个持久层,将数据库访问封装在一些服务类中。这也使更改数据库变得更加容易。
  • 持久连接与以模块化方式构建应用程序无关......但无论如何,如果可以,请使用持久连接。我只是指出它与每个进程有单独的连接并不完全相同。
【解决方案2】:

来自PHP Docs

如果创建到 SQL 服务器的链接的开销很高,则持久连接很好。

但是,请注意,如果您使用的数据库的连接限制被持久子连接所超过,这可能会有一些缺点。如果您的数据库有 16 个同时连接的限制,并且在繁忙的服务器会话过程中,有 17 个子线程尝试连接,则一个将无法连接。

持久连接不能解决您的问题。您的问题是您的突发使用超出了数据库配置中设置的限制,并且可能超出了您的基础设施。您的 CTO 所做的增加连接限制是很好的第一步。现在您需要监控数据库服务器上的资源利用率,以确保它们能够处理来自额外连接的增加的负载。如果他们可以,你很好。如果您开始看到数据库服务器的资源不足,则需要设置额外的服务器来处理流量激增。

【讨论】:

  • 我的 php 应用程序如何/何时产生持久的子连接?我相信它始终只与 MySQL 服务器保持 1 个持久连接来发送所有查询,无论它获得多少并发用户。 [鉴于我在任何 php 脚本之上包含以下行:$db = new mysqli('p:db_server_ip', 'db_user', 'db_user_pass', 'db_name');]
  • 每个线程都必须有自己的连接,因此它不是每个服务器的单个连接,而是每个线程的单个连接。如果您有 10 台服务器,每台服务器有 10 个线程,则总共需要 100 个连接。持久连接只会为您节省连接的设置和拆卸。它们值得使用,但它们无法解决服务器没有足够可用连接的问题。
【解决方案3】:

连接太多

原因 这是错误是由

引起的
  • 大量同时连接,或
  • 由于旧连接没有尽快释放

你已经做了SHOW VARIABLES LIKE "max_connections";并增加了价值。

永久连接

如果您使用永久或 persistent database connections,则必须始终考虑 MySQL 指令 wait_timeout。关闭将不起作用,但您可以降低超时。因此,使用过的资源将更快地再次可用。使用netstat 找出发生了什么,完全按照这里https://serverfault.com/questions/355750/mysql-lowering-wait-timeout-value-to-lower-number-of-open-connections 的描述。

不要忘记释放结果集以减少数据库服务器资源的浪费。

建议使用临时的、短暂的连接而不是持久连接。 引入持久性几乎是针对整个 Web 请求-响应流程的,因为它是无状态的。您知道:1 个 pconnect 请求会导致 8 小时的持久连接在 db 服务器上悬空,等待下一个请求,而该请求永远不会到来。乘以用户数量并查看您的资源。

临时连接

如果你使用 mysql_connect() - 不要忘记使用 mysql_close()。 将 new_link 设置为 false 并传递 CLIENT_INTERACTIVE 标志。 您可以调整interactive_timeout,这有助于阻止旧连接阻塞工作。

如果问题仍然存在,请扩展

如果问题仍然存在,则决定扩大规模。 通过添加另一个数据库服务器并在前面放置一个代理, (MySQL 可以很好地与 HAProxy 配合使用)或切换到自动扩展的云服务。

我真的怀疑你的东西是否配置正确。 当您已经在运行多个 MySQL 服务器以及多个 Web 服务器时,这怎么会是一个问题?请描述您的负载平衡设置。

听起来像是 Apache 2.2 + mod_php + MySQL + 未知平衡器,对吧?

不妨试试

【讨论】:

  • 10k 并发用户。每日用户约为 50 万。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-04
  • 1970-01-01
  • 1970-01-01
  • 2016-08-31
  • 2021-10-16
  • 1970-01-01
相关资源
最近更新 更多