在 PHP 中使用 PDO 打开的 SQL 连接是不是必须关闭

Posted

技术标签:

【中文标题】在 PHP 中使用 PDO 打开的 SQL 连接是不是必须关闭【英文标题】:Do SQL connections opened with PDO in PHP have to be closed在 PHP 中使用 PDO 打开的 SQL 连接是否必须关闭 【发布时间】:2010-11-06 00:08:59 【问题描述】:

当我只使用 php 的内置 mysql 函数在 PHP 中打开 MySQL 连接时,我会执行以下操作:

$link = mysql_connect($servername, $username, $password);
mysql_select_db($dbname);
//queries etcetera
mysql_close($link);

当我打开与 PDO 的连接时,它看起来像这样:

$link = new PDO("mysql:dbname=$dbname;host=$servername",$username,$password);
//prepare statements, perform queries

我是否必须像使用 mysql_connect()mysql_close() 一样明确关闭连接?如果没有,PHP 如何知道我的连接何时完成?

TIA。

【问题讨论】:

【参考方案1】:

使用$link = null 让 PDO 知道它可以关闭连接。

PHP: PDO Connections & Connection Management

成功连接到数据库后,PDO 类的实例将返回到您的脚本。该连接在该 PDO 对象的生命周期内保持活动状态。要关闭连接,您需要通过确保删除对它的所有剩余引用来销毁该对象——您通过将 NULL 分配给保存该对象的变量来做到这一点。如果您没有明确地这样做,PHP 将在您的脚本结束时自动关闭连接。

【讨论】:

我想知道 PDO dtor 是显式关闭连接还是将其留给 PHP,就像在脚本末尾未使用 mysql_close() 时(或在您的 __destruct()数据库类)?从手册看来,当 PDO 对象被破坏时,连接也会关闭。因此很重要:***.com/a/2960656/372654。从 PDO 源代码看来是这样,但是... 不会有一个unset() PDO 对象而不是将其设置为 NULL 吗?我真的很想澄清一下! 值得注意的是,官方 PHP 手册(根据上面的链接)建议设置为 null,并且没有提及“unset()”。您是在使用官方方法时遇到问题,还是在学术上询问?如果是前者,请详细说明。如果是后者,您可能想联系 PHP 开发人员,他们最适合解决官方记录的解决方案的替代方案。 (例如,即使 unset() 在一个版本中有效,如果开发人员没有明确确保该方法,它也可能在另一个版本中无效。) 恕我直言,您 unset() 或设置为 NULL 都没有关系。 AFAIK,无论哪种方式,PDO::__destruct 方法的调用方式与您让变量持续到脚本结束并在该方法中关闭连接的方式相同。 范围怎么样?如果连接对象被实例化并且没有在函数/方法结束时返回,连接会死吗?【参考方案2】:

PHP 脚本执行完毕后,所有连接都将关闭。此外,您不必明确关闭与mysql_close() 的连接。

【讨论】:

【参考方案3】:

http://uk3.php.net/pdo

从我收集的信息来看,我无论如何都无法在 php 手册中关闭它,而且我快速查看的脚本示例从我所看到的任何情况下都不会关闭连接。

【讨论】:

【参考方案4】:

您还可以将连接限制在本地函数内。这样功能一完成,连接就会关闭。

【讨论】:

【参考方案5】:

PDO 本身不提供这样的功能。通过 PDO 的连接是通过 PHP 中的 PDO 对象引用计数间接管理的。

但有时您无论如何都想关闭连接,而不管引用计数如何。要么是因为您无法控制它,要么出于测试目的需要它。

您可以通过运行 SQL 查询来关闭 Mysql 与 PDO 的连接。每个能够连接到 Mysql 服务器的用户都能够KILL 至少自己的线程:

/*
 * Close Mysql Connection (PDO)
 */

$pdo_mysql_close = function (PDO $connection) 

    $query = 'SHOW PROCESSLIST -- ' . uniqid('pdo_mysql_close ', 1);
    $list  = $connection->query($query)->fetchAll(PDO::FETCH_ASSOC);
    foreach ($list as $thread) 
        if ($thread['Info'] === $query) 
            return $connection->query('KILL ' . $thread['Id']);
        
    
    return false;
;

$pdo_mysql_close($conn);

Mysql 相关文档:

13.7.5.30. SHOW PROCESSLIST Syntax 13.7.6.4. KILL Syntax

相关 *** 问题:

PHP PDO close()?(2012 年 4 月)

【讨论】:

$connection->query('KILL CONNECTION_ID();'); 在 debian 上通过本地 mysql 命令行客户端和 Windows 工作站上的工作台测试 mysql 5.7。根据dev.mysql.com/doc/refman/5.5/en/show-processlist.html,SHOW PROCESSLIST 列Id 是“...连接标识符。这是在 INFORMATION_SCHEMA PROCESSLIST 表的 ID 列中显示并由 CONNECTION_ID() 函数返回的相同类型的值。” (注意:我正在评论一个将近 6 岁的答案)【参考方案6】:

因为 PDO 的 $link 被分配了一个对象,所以 PHP 会在脚本运行时将其设置为 null,这样它就不再是一个对象。因此你可以这样做:

$link = new PDO("mysql:dbname=$dbname;host=$servername",$username,$password);

//prepare statements, perform queries

$link = null;

【讨论】:

以上是关于在 PHP 中使用 PDO 打开的 SQL 连接是不是必须关闭的主要内容,如果未能解决你的问题,请参考以下文章

PDO-数据库访问抽象层

php+mysql 请问:用pdo如何获取某个表中记录的数目?

php+mysql 请问:用pdo如何获取某个表中记录的数目?

thinkphp3.2连接 Postgres SQL

使用 PDO_DBLIB 连接到 MS SQL 数据库的 PHP 错误

PHP中的PDO对象操作学习初始化PDO及原始SQL语句操作