V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
thomaswang
V2EX  ›  PHP

PHP 短连 mysql

  •  
  •   thomaswang · 2017-06-03 10:40:13 +08:00 · 4211 次点击
    这是一个创建于 2733 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一个 php-fpm 进程处理两次请求(都是需要操作数据库),但是在 php 程序里面没有释放 mysql 的连接,请求,php-fpm 在处理第二次请求之前,会释放掉 mysql 连接吗,如果不是,那第一次的这个连接什么时候释放呢?
    18 条回复    2020-09-21 08:59:35 +08:00
    orderc
        1
    orderc  
       2017-06-03 11:04:20 +08:00   ❤️ 1
    php request 处理完成就释放了
    FYK
        2
    FYK  
       2017-06-03 11:11:38 +08:00 via iPhone
    每次的请求都是独立的,然后 php 脚本每次执行完都会释放所有资源。
    thomaswang
        3
    thomaswang  
    OP
       2017-06-03 11:28:49 +08:00
    @FYK 如果 php 代码里面写的是长连接的话,第一次请求完成之后,就不释放 mysql 连接,对吗
    edison111cry
        4
    edison111cry  
       2017-06-03 11:48:05 +08:00
    @thomaswang 应该也会释放吧,PHP-FPM 只是一个进程,执行你的 PHP 代码,在内存生成变量,连接数据库资源,等这个进程执行完,肯定会把自己进程空间里的所有资源释放掉了。不知道我理解的对不对
    FYK
        5
    FYK  
       2017-06-03 12:32:20 +08:00
    @thomaswang

    [`mysql_pconnect`]( http://php.net/manual/zh/function.mysql-pconnect.php)
    >`mysql_pconnect()` 和 `mysql_connect()` 非常相似,但有两个主要区别。
    >首先,当连接的时候本函数将先尝试寻找一个在同一个主机上用同样的用户名和密码已经打开的(持久)连接,如果找到,则返回此连接标识而不打开新连接。
    >其次,当脚本执行完毕后到 `SQL` 服务器的连接不会被关闭,此连接将保持打开以备以后使用(`mysql_close()` 不会关闭由 `mysql_pconnect()` 建立的连接)。
    >可选参数 `client_flags` 自 `PHP 4.3.0` 版起可用。
    >此种连接称为“持久的”。

    [`mysqli::__construct`]( http://php.net/manual/zh/mysqli.construct.php)
    >Prepending host by p: opens a persistent connection. `mysqli_change_user()` is automatically called on connections opened from the connection pool.

    [`mysqli::change_user`]( http://php.net/manual/zh/mysqli.change-user.php)
    >Changes the user of the specified database connection.
    FYK
        6
    FYK  
       2017-06-03 12:35:52 +08:00
    。。。看帖多,回帖少,还不知道回复不支持 markdown 语法。所以回复阅读起来可能会有些费力,见谅。
    thomaswang
        7
    thomaswang  
    OP
       2017-06-03 13:07:11 +08:00
    @edison111cry 我做了个实验,php pdo 长连 mysql,然后我看 mysql 连接数( show full processlist ),连接数 = php-fpm 进程数,而且这些 mysql 连接是不会变的(不消失,不新建),把 php-fpm 进程杀了,就消失了
    edison111cry
        8
    edison111cry  
       2017-06-03 14:16:46 +08:00 via iPhone
    @thomaswang
    那这样是不是因为之前 PHP-FPM 就没有结束呢?一直在执行?
    thomaswang
        9
    thomaswang  
    OP
       2017-06-03 14:43:38 +08:00
    @FYK 当我们创建的数据连接为 PDO 持久化连接时,该连接在使用完毕或者 PHP 脚本结束后并不会被关闭,而是被 PHP 缓存起来。当另一个使用相同凭证(主机、端口、数据库名、用户名、密码等信息完全一致)的 PHP 脚本请求建立连接时,PHP 将直接返回之前被缓存起来的连接,从而达到连接重用。持久连接缓存可以避免每次访问数据库都要建立一个新连接的开销,从而让 web 应用程序更快。和你那个一样,你看 7 楼我做的实验,这个缓存应该缓存到当前 php-fpm 进程中了,不然一台机器只会有一个 mysql 连接,实验下来等于 php-fpm 进程数
    hasdream
        10
    hasdream  
       2017-06-03 15:09:30 +08:00   ❤️ 1
    php 支持 pdo_mysql 和 mysql 驱动长连接 请求完成后不释放支持复用 和 redis 的 pconnect 类似
    thomaswang
        11
    thomaswang  
    OP
       2017-06-03 15:25:52 +08:00
    @hasdream 这个复用是每个 php-fpm 进程内部复用,对吗? 也就是说一个 php-fpm 和 mysql 建立连接之后, 以后这个 php-fpm 处理的请求,都用这个连接,那么 php-fpm 的进程数 == mysql 连接数,而且这个连接不会被释放,直到杀 php-fpm 进程的时候,才释放。对吗
    FYK
        12
    FYK  
       2017-06-03 17:17:39 +08:00   ❤️ 1
    @thomaswang 没错。另外,楼主对 php-fpm 理解似乎有一点偏差。

    详情可见 :
    [FastCGI 进程管理器( FPM )]( http://php.net/manual/zh/install.fpm.php)
    [什么是 CGI、FastCGI、PHP-CGI、PHP-FPM、Spawn-FCGI ?]( http://www.mike.org.cn/articles/what-is-cgi-fastcgi-php-fpm-spawn-fcgi/)

    [数据库持久连接]( http://php.net/manual/zh/features.persistent-connections.php):

    >第二,也是最常用的方法,是把 PHP 用作多进程 web 服务器的一个模块,这种方法目前只适用于 Apache。对于一个多进程的服务器,其典型特征是有一个父进程和一组子进程协调运行,其中实际生成 web 页面的是子进程。每当客户端向父进程提出请求时,该请求会被传递给还没有被其它的客户端请求占用的子进程。这也就是说当相同的客户端第二次向服务端提出请求时,它将有可能被一个不同的子进程来处理。在开启了一个持久连接后,所有请求 SQL 服务的后继页面都能够重用这个已经建立的 SQL Server 连接。

    >如果持久连接并没有任何附加的功能,那么使用它有什么好处?

    >答案非常简单——效率。当 Web Server 创建到 SQL 服务器的连接耗费(Overhead)较高(如耗时较久,消耗临时内存较多)时,持久连接将更加高效。Overhead 高低取决于很多因素。例如,数据库的种类,数据库服务和 web 服务是否在同一台服务器上,SQL 服务器负载状况等。当 Overhead 较高,每次创建数据库连接成本较高时,持久连接将显著的提高效率。它使得每个子进程在其生命周期中只做一次连接操作,而非每次在处理一个页面时都要向 SQL 服务器提出连接请求。这也就是说,每个子进程将对服务器建立各自独立的持久连接。例如,如果有 20 个不同的子进程运行某脚本建立了持久的 SQL 服务器持久连接,那么实际上向该 SQL 服务器建立了 20 个不同的持久连接,每个进程占有一个。
    fyibmsd
        13
    fyibmsd  
       2017-06-03 18:20:05 +08:00
    pdo 如果用了 PDO::ATTR_PERSISTENT,fpm 会和 mysql 建立长连接,netstat 看 state 就会是 ESTABLISHED
    hasdream
        14
    hasdream  
       2017-06-03 19:10:19 +08:00
    @thomaswang php-fpm 工作进程处理下一个请求的时候直接复用这个 mysql 长连接 , 除非空闲时间超过 8 小时 就会被 mysql 服务器 kill 这个连接
    abcbuzhiming
        15
    abcbuzhiming  
       2017-06-04 16:37:18 +08:00
    如果 php pdo 用的是短连接,那么连接的生命周期就是本次请求的生命周期,请求结束,所有资源被释放,如果使用的是长连接,那么会被 php-fpm hold 住连接供以后使用
    thomaswang
        16
    thomaswang  
    OP
       2017-06-04 20:56:53 +08:00
    @abcbuzhiming 有比较详细和权威的文档吗,谢谢
    abcbuzhiming
        17
    abcbuzhiming  
       2017-06-04 21:12:43 +08:00
    @thomaswang 权威的话,PHP 自己的文档就已经很权威了啊,详细的说明了连接数据库的长短连接的模型,不过关键点在于长连接的时候如何 hold 住连接,因为 php 是一种一次请求后基本就会把自己释放掉的技术,我以前一直以为只有 php-fpm 可以 hold 住连接,后来做试验发现,其实在 windows 下的 IIS+fastcgi 也可以,hold 住连接的是 IIS 的进程池。可见 PHP 的 pod 长连接在不同的操作系统下实现不同
    Donne
        18
    Donne  
       2020-09-21 08:59:35 +08:00
    使用这种长连接,PHP 主动释放链接只能通过重启 PHP-FPM 来实现吗?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5340 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 08:11 · PVG 16:11 · LAX 00:11 · JFK 03:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.