PHP中的连接池技术

89

在使用PHP时,是否可以像在J2EE容器中一样缓存数据库连接?如果可以,如何实现?


1
你看过使用mysql_pconnect()来建立持久连接吗? - Chris Bartow
这个怎么样?https://github.com/junamai2000/mod_namy_pool - nam
实际上PHP中有关连接池的内容,可以查看手册:http://php.net/manual/zh/mysqlnd-ms.pooling.php 和 http://php.net/manual/zh/mysqlnd-mux.connection_pool.php。 - Felix Huang
9个回答

63

在 PHP 中没有 连接池
mysql_pconnect连接池 是两个不同的概念。 使用 mysql_pconnect 存在许多问题,你应该仔细阅读手册并小心使用,但这并不是连接池。

连接池是一种技术,应用服务器管理连接。当应用程序需要连接时,它会向应用服务器请求连接,如果有空闲的连接,则应用服务器返回其中一个池化的连接。

我们可以在 PHP 中进行连接缩放,请参考以下链接:http://www.oracle.com/technetwork/articles/dsl/white-php-part1-355135.html

所以在 PHP 中没有连接池。

正如 Julio 所说,Apache 在当前请求结束时释放所有资源。你可以使用 mysql_pconnect,但是你受到该函数的限制,必须非常小心。另一个选择是使用单例模式,但这些都不是连接池。

这是一篇好文章:https://blogs.oracle.com/opal/highly-scalable-connection-pooling-in-php

还要阅读这篇文章:http://www.apache2.es/2.2.2/mod/mod_dbd.html


26
没有连接池?哇。 - Justin
2
当脚本执行结束时,与SQL服务器的连接不会关闭。 - RandomSeed
2
Oracle博客的工作链接:https://blogs.oracle.com/opal/entry/highly_scalable_connection_poo - LMC
@Justin 看看 swoole/openswoole - 这是一个广泛流行的 PHP 扩展,基本上使 PHP 异步化并添加了大量企业级功能。你可以很容易地使用它在 PHP 中实现连接池:例如,参见 https://github.com/open-smf/connection-pool,参见 https://hyperf.wiki/2.2/#/en/pool。我正在使用它与 pdo/mysql 和 phpredis - 真是太棒了! - Dannyboy
1
如果是这种情况,那么在这个背景下,J2EE或Java是否比PHP更好呢?换句话说,PHP如何解决每次向服务器发出请求时都需要重新连接到数据库的问题? - Adelin

19
持久化连接与连接池完全不同。在php中,仅当您在同一请求/脚本执行上下文中进行多个数据库连接时,才会重用持久化连接。在大多数典型的Web开发场景中,如果使用mysql_pconnect,您的脚本将无法在下一个请求中获取到任何打开连接的引用,这样很快就会耗尽您的连接。在php中使用数据库连接的最佳方法是创建数据库对象的单例实例,以便在您的脚本执行上下文中复用连接。这仍然会在每个请求中产生至少1个数据库连接,但比在每个请求中进行多次数据库连接更好。
由于php的特性,实际上没有真正的数据库连接池。Php不是可以坐在请求之间并管理对一组打开连接的引用的应用程序服务器,至少不是没有某种主要手段的情况下。我认为理论上您可以在php中编写一个应用程序服务器,并将其作为命令行脚本运行,它将继续在后台保持一堆数据库连接,并将对它们的引用传递给其他脚本,但我不知道如何将对命令行脚本的引用传递给其他脚本,而且即使您能够完成这项工作,我也认为这样做的性能问题可能会很大。无论如何,这基本上是推测。我刚刚注意到其他人发布的链接,可以在prefork服务器(例如php)中允许连接池。看起来很有趣:https://github.com/junamai2000/mod_namy_pool#readme

3
当脚本执行结束时,与 SQL 服务器的连接不会关闭。 - RandomSeed
在PHP中使用数据库连接的最佳方式是创建一个数据库对象的单例实例,以便在脚本执行的上下文中重复使用连接。这正是我正在寻找的黄金方法!非常好地解释了单例在何时何地会有用! - samazi

14

我猜你正在使用mod_php,对吗?

当PHP文件执行完成后,它的所有状态都会被清除,所以无法在PHP代码中进行连接池。相反,你必须依靠扩展。

你可以使用mysql_pconnect,这样连接就不会在页面结束后关闭,它们会在下一个请求中被重用。

这可能就是你需要的全部内容,但这并不等同于连接池,因为没有办法指定要维护打开的连接数。


3
不同用户可以重用连接吗?如果可以,那为什么手册上说我们应该配置MySQL以避免太多的连接? - omg

11

你可以使用MySQLi

更多信息,请滚动到连接池部分

请注意,连接池也取决于您的服务器(即 Apache httpd)及其配置。


2
这个回答应该被点赞,因为其他所有回答都非常陈旧。连接池及其可能引起的问题是非常真实的! - Alexp

2
如果在打开的连接池中找不到给定的“主机、用户名、密码、套接字、端口和默认数据库组合”的未使用持久连接,则只有mysqli会打开新连接,否则它将重用已经打开的可用持久连接,这在某种程度上类似于连接池的概念。可以使用PHP指令mysqli.allow_persistent启用和禁用持久连接。脚本打开的连接总数可以通过mysqli.max_links限制(这可能对您来说很有趣,以解决达到托管服务器限制的max_user_connections问题)。每个PHP进程的最大持久连接数可以通过mysqli.max_persistent限制。
在更广泛的编程环境中,这是Web /应用程序服务器的任务,但在此上下文中,它由PHP自身的mysqli指令处理,以支持连接可重用性。您还可以实现单例类以获取静态连接实例以便重用,就像在Java中一样。只想提醒一下,Java也不支持作为其标准JDBC的连接池,它们是基于JDBC驱动程序的不同模块/层。

关于PHP,好消息是对于PHP生态中常见的数据库,它支持持久性数据库连接,可以将连接保留500个请求(在php.ini中配置max_requests),这避免了每次请求都创建新的连接。详细信息请参阅文档,它可以解决大多数问题。请注意,与严格面向对象的Java相比,在强大的异步事件处理、广泛的多线程机制和并发处理方面,PHP并不是那么复杂。因此,从某种意义上讲,像连接池这样的内置机制对于PHP的有效性来说非常低。


1
我想建议使用PDO::ATTR_PERSISTENT
持久连接是指在脚本执行结束后不会关闭的链接。当请求一个持久连接时,PHP会检查是否已经存在相同的持久连接(之前保持打开状态),如果存在,则使用它。如果不存在,则创建该链接。

0

连接池在MySQL服务器端的工作方式如下。

  1. 如果启用了持久连接,则MySQL会在请求的客户端(php脚本)完成其工作并死亡后保持连接处于睡眠状态。
  2. 当第二个请求使用相同的凭据数据(相同的用户名、相同的密码、相同的连接参数、相同的数据库名称,可能来自相同的IP,我不确定IP)时,MySQL将从睡眠状态池中获取先前的连接,并让客户端使用该连接。这有助于MySQL节省连接的初始资源和减少总连接数。

因此,连接池选项实际上是在MySQL服务器端可用的。在PHP代码端没有选项。mysql_pconnect()只是一个包装器,通知PHP在脚本运行结束时不发送连接关闭请求信号。


0

您不能手动实例化连接池。

但是,您可以使用mysql_pconnect函数中的“内置”连接池。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接