MySQL 函数 (PDO_MYSQL)

简介

PDO_MYSQL 是一个驱动程序,它实现了 PHP 数据对象 (PDO) 接口,以允许从 PHP 访问 MySQL 数据库。

PDO_MYSQL 默认使用模拟准备。

MySQL 8

在运行 PHP 版本早于 7.1.16 或 PHP 7.2 早于 7.2.4 时,请将 MySQL 8 服务器的默认密码插件设置为 mysql_native_password,否则您将看到类似于 服务器请求客户端未知的身份验证方法 [caching_sha2_password] 的错误,即使未使用 caching_sha2_password

这是因为 MySQL 8 默认使用 caching_sha2_password,该插件不被旧版 PHP (mysqlnd) 版本识别。相反,通过在 my.cnf 中设置 default_authentication_plugin=mysql_native_password 来更改它。从 PHP 7.4.4 开始完全支持 caching_sha2_password 插件。对于较旧的版本,mysql_xdevapi 扩展确实支持它。

警告

注意:一些 MySQL 表类型(存储引擎)不支持事务。当使用不支持事务的表类型编写事务性数据库代码时,MySQL 将假装已成功启动事务。此外,任何发出的 DDL 查询将隐式提交任何挂起的交易。

注意:

MySQL 驱动程序不支持 PDO::PARAM_INPUT_OUTPUT 通过 PDOStatement::bindParam();虽然可以使用此类参数,但它们不会更新(即实际输出被忽略)。

安装

常见的 Unix 发行版包含可以安装的 PHP 二进制版本。尽管这些二进制版本通常是在支持 MySQL 扩展的情况下构建的,但扩展库本身可能需要使用额外的软件包进行安装。检查您选择的发行版附带的软件包管理器以查看可用性。

例如,在 Ubuntu 上,php5-mysql 包安装 ext/mysql、ext/mysqli 和 PDO_MYSQL PHP 扩展。在 CentOS 上,php-mysql 包也安装了这三个 PHP 扩展。

或者,您可以自己编译此扩展。从源代码构建 PHP 允许您指定要使用的 MySQL 扩展,以及您为每个扩展选择的客户端库。

编译时,使用 --with-pdo-mysql[=DIR] 安装 PDO MySQL 扩展,其中可选的 [=DIR] 是 MySQL 基本库。 Mysqlnd 是默认库。有关选择库的详细信息,请参阅 选择 MySQL 库

可选地,--with-mysql-sock[=DIR] 设置为所有 MySQL 扩展(包括 PDO_MYSQL)的 MySQL unix 套接字指针的位置。如果未指定,则会搜索默认位置。

可选地,--with-zlib-dir[=DIR] 用于设置 libz 安装前缀的路径。

$ ./configure --with-pdo-mysql --with-mysql-sock=/var/mysql/mysql.sock

SSL 支持使用适当的 PDO_MySQL 常量 启用,这等效于调用 » MySQL C API 函数 mysql_ssl_set()。此外,无法使用 PDO::setAttribute 启用 SSL,因为连接已存在。另请参阅有关 » 使用 SSL 连接到 MySQL 的 MySQL 文档。

预定义常量

以下常量由此驱动程序定义,并且只有在已将扩展编译到 PHP 中或在运行时动态加载时才可用。此外,这些特定于驱动程序的常量仅在使用此驱动程序时使用。将特定于驱动程序的属性与另一个驱动程序一起使用可能会导致意外行为。 PDO::getAttribute() 可用于获取 PDO::ATTR_DRIVER_NAME 属性以检查驱动程序,如果您的代码可以在多个驱动程序上运行。

PDO::MYSQL_ATTR_USE_BUFFERED_QUERY (bool)
默认情况下,所有语句都在 缓冲模式 下执行。如果此属性在 PDO 对象上设置为 false,则 MySQL 驱动程序将使用非缓冲模式。

示例 #1 设置 MySQL 非缓冲模式

<?php
$pdo
= new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_password');
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

$unbufferedResult = $pdo->query("SELECT Name FROM City");
foreach (
$unbufferedResult as $row) {
echo
$row['Name'] . PHP_EOL;
}
?>

PDO::MYSQL_ATTR_LOCAL_INFILE (int)

启用 LOAD LOCAL INFILE

注意,此常量只能在构建新数据库句柄时在 driver_options 数组中使用。

PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY (string)

允许将 LOCAL DATA 加载限制到位于此指定目录中的文件。从 PHP 8.1.0 开始可用。

注意,此常量只能在构建新数据库句柄时在 driver_options 数组中使用。

PDO::MYSQL_ATTR_INIT_COMMAND (string)

连接到 MySQL 服务器时要执行的命令。在重新连接时会自动重新执行。

注意,此常量只能在构建新数据库句柄时在 driver_options 数组中使用。

PDO::MYSQL_ATTR_READ_DEFAULT_FILE (int)

从指定的选项文件而不是从 my.cnf 中读取选项。如果使用 mysqlnd,则此选项不可用,因为 mysqlnd 不读取 mysql 配置文件。

PDO::MYSQL_ATTR_READ_DEFAULT_GROUP (int)

my.cnf 中的指定组或使用 MYSQL_READ_DEFAULT_FILE 指定的文件中读取选项。如果使用 mysqlnd,则此选项不可用,因为 mysqlnd 不读取 mysql 配置文件。

PDO::MYSQL_ATTR_MAX_BUFFER_SIZE (int)

最大缓冲区大小。默认为 1 MiB。当针对 mysqlnd 编译时,此常量不受支持。

PDO::MYSQL_ATTR_DIRECT_QUERY (int)

执行直接查询,不要使用准备好的语句。

PDO::MYSQL_ATTR_FOUND_ROWS (int)

返回找到(匹配)的行数,而不是更改的行数。

PDO::MYSQL_ATTR_IGNORE_SPACE (int)

允许函数名称后面的空格。使所有函数名称成为保留字。

PDO::MYSQL_ATTR_COMPRESS (int)

启用网络通信压缩。

PDO::MYSQL_ATTR_SSL_CA (int)

SSL 证书颁发机构的文件路径。

PDO::MYSQL_ATTR_SSL_CAPATH (int)

包含受信任 SSL CA 证书的目录的文件路径,这些证书存储在 PEM 格式中。

PDO::MYSQL_ATTR_SSL_CERT (int)

SSL 证书的文件路径。

PDO::MYSQL_ATTR_SSL_CIPHER (int)

一个或多个可用于 SSL 加密的允许密码列表,格式应为 OpenSSL 可识别格式。例如:DHE-RSA-AES256-SHA:AES128-SHA

PDO::MYSQL_ATTR_SSL_KEY (int)

SSL 密钥的文件路径。

PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT (int)

提供了一种禁用服务器 SSL 证书验证的方法。此选项仅在使用 mysqlnd 时可用。

此选项从 PHP 7.0.18 和 PHP 7.1.4 开始提供。

PDO::MYSQL_ATTR_MULTI_STATEMENTS (int)

当设置为 false 时,将禁用 PDO::prepare()PDO::query() 中的多查询执行。

注意,此常量只能在构建新数据库句柄时在 driver_options 数组中使用。

运行时配置

这些函数的行为受 php.ini 中设置的影响。

PDO_MYSQL 配置选项
名称 默认值 可更改
pdo_mysql.default_socket "/tmp/mysql.sock" INI_SYSTEM
pdo_mysql.debug NULL INI_SYSTEM
有关 INI_* 模式的更多详细信息和定义,请参见 配置设置可设置的位置

以下是配置指令的简要说明。

pdo_mysql.default_socket string

设置 Unix 域套接字。如果在配置时找到了域套接字,则此值可以在编译时设置。此 ini 设置仅适用于 Unix。

pdo_mysql.debug bool

启用 PDO_MYSQL 的调试。此设置仅在 PDO_MYSQL 针对 mysqlnd 编译并在 PDO 调试模式下可用。

目录

添加说明

用户贡献说明 8 notes

Desislav Kamenov
6 年前
有一个重要的未记录的属性,可以在
5.6.22(不确定),7.0.18(已验证)和 7.1.15(不确定)之后禁用证书 CN 验证

PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT

可能的值:true,false
默认值:true

相关 PHP 错误
https://bugs.php.net/bug.php?id=71845
https://bugs.php.net/bug.php?id=71003

以及 github PR:https://github.com/php/php-src/pull/1913
brian at diamondsea dot com
16 年前
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. ...

在花费数小时尝试追踪为什么我们在新服务器上遇到此错误之后,而在其他服务器上相同的代码运行良好,我们发现问题是我们的 Web 服务器上运行的旧 MySQL _client_ 库,以及数据库服务器上运行的最新版本的 MySQL _server_。

将 Web 服务器上的 MySQL 客户端升级到当前版本,问题就消失了。
davey at php dot net
17 年前
要使用“PDO::MYSQL_ATTR_USE_BUFFERED_QUERY”,您应该调用
PDO::setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);

传递给 PDO::prepare() 时它不会起作用
curt at webmasterbond dot com
13 年前
今天的 PHP 快照现在支持 PDO 的 SSL。请按照此处说明(https://dev.mysqlserver.cn/doc/refman/5.0/en/secure-create-certs.html)设置 MySQL,然后使用以下连接选项

<?php
$pdo
= new PDO(
'mysql:host=hostname;dbname=ssldb',
'username',
'password',
array(
PDO::MYSQL_ATTR_SSL_KEY =>'/path/to/client-key.pem',
PDO::MYSQL_ATTR_SSL_CERT=>'/path/to/client-cert.pem',
PDO::MYSQL_ATTR_SSL_CA =>'/path/to/ca-cert.pem'
)
);
?>
rmottey at gmail dot com
16 年前
我在单个页面中执行多个查询时一直遇到以下错误。

设置下面的属性对我来说似乎不起作用。

因此,根据之前的示例,我在每个查询上都初始化我的 stmt 变量,并将所有内容提取到一个数组中。对我来说似乎有效。

错误
PDO 错误 1.1:数组([0] => xxx[1] => yyy[2] => Lost connection to MySQL server during query)

修复

(PDO::setAttribute("PDO::MYSQL_ATTR_USE_BUFFERED_QUERY", true);)

<?

try {
$dbh = new PDO('mysql:host=xxx;port=xxx;dbname=xxx', 'xxx', 'xxx', array( PDO::ATTR_PERSISTENT => false));
$stmt = $dbh->prepare("CALL getname()");

// 调用存储过程
$stmt->execute();
// 将所有行提取到数组中。
$rows = $stmt->fetchAll();
foreach ($rows as $rs)
{
$id = $rs['id'];
}
// 初始化语句
unset($stmt);
$stmt = $dbh->prepare("call secondprocedure(?);");
$stmt->bindValue(1, $id);
if ( ! $stmt->execute() )
{
echo "PDO 错误 1.1:\n";
print_r($stmt->errorInfo());
exit;
}
unset($stmt);
} catch (PDOException $e) {
print "错误!: " . $e->getMessage() . "<br/>";
die();
}
?>
miller_kurt_e at yahoo dot com
16 年前
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. ...

这个很难处理。永远不要将要执行的语句堆叠起来。在我看到的所有处理此错误的帖子中,都没有人提到过这种可能性。

此示例是一个 Zend Framework 示例,但原理相同。

例如

<?php
$sql
= <<<____SQL
CREATE TABLE IF NOT EXISTS `ticket_hist` (
`tid` int(11) NOT NULL,
`trqform` varchar(40) NOT NULL,
`trsform` varchar(40) NOT NULL,
`tgen` datetime NOT NULL,
`tterm` datetime,
`tstatus` tinyint(1) NOT NULL
) ENGINE=ARCHIVE COMMENT='ticket archive';
CREATE TABLE IF NOT EXISTS `request_hist` (
`rqid` int(11) NOT NULL,
`rqtid` int(11) NOT NULL,
`rqsid` int(11) NOT NULL,
`rqdate` datetime NOT NULL,
`rqcode` tinyint(1) NOT NULL,
`rssid` int(11) NOT NULL,
`rsdate` datetime,
`rscode` tinyint(1)
) ENGINE=ARCHIVE COMMENT='request archive';
CREATE TABLE IF NOT EXISTS `relay_hist` (
`rqid` int(5) NOT NULL,
`sdesc` varchar(40) NOT NULL,
`rqemail` varchar(40) NOT NULL,
`sid` int(11) NOT NULL,
`rlsid` int(11) NOT NULL,
`dcode` varchar(5) NOT NULL
) ENGINE=ARCHIVE COMMENT='relay archive';
____SQL;
$result = $this->db->getConnection()->exec($sql);
?>

这将正常运行,但如果您在此之后执行另一个查询,PDO 会因“未缓冲”错误而报错。

相反,请执行以下操作

<?php
$sql
= <<<____SQL
CREATE TABLE IF NOT EXISTS `ticket_hist` (
`tid` int(11) NOT NULL,
`trqform` varchar(40) NOT NULL,
`trsform` varchar(40) NOT NULL,
`tgen` datetime NOT NULL,
`tterm` datetime,
`tstatus` tinyint(1) NOT NULL
) ENGINE=ARCHIVE COMMENT='ticket archive';
____SQL;
$result = $this->db->getConnection()->exec($sql);

$sql = <<<____SQL
CREATE TABLE IF NOT EXISTS `request_hist` (
`rqid` int(11) NOT NULL,
`rqtid` int(11) NOT NULL,
`rqsid` int(11) NOT NULL,
`rqdate` datetime NOT NULL,
`rqcode` tinyint(1) NOT NULL,
`rssid` int(11) NOT NULL,
`rsdate` datetime,
`rscode` tinyint(1)
) ENGINE=ARCHIVE COMMENT='request archive';
____SQL;
$result = $this->db->getConnection()->exec($sql);

$sql = <<<____SQL
CREATE TABLE IF NOT EXISTS `relay_hist` (
`rqid` int(5) NOT NULL,
`sdesc` varchar(40) NOT NULL,
`rqemail` varchar(40) NOT NULL,
`sid` int(11) NOT NULL,
`rlsid` int(11) NOT NULL,
`dcode` varchar(5) NOT NULL
) ENGINE=ARCHIVE COMMENT='relay archive';
____SQL;
$result = $this->db->getConnection()->exec($sql);
?>

将它们分成单独的查询可以解决问题。
vafa ghoreyshi atgmailcom
6 年前
如果您遇到“找不到驱动程序”错误,并且无法为更新的 Linux(Fedora、Redhat、CentOS)安装最新版本的 PHP7/MariaDB10/Apache2.4 的驱动程序,请安装此软件包,然后一切都会顺利进行。
首先,下载适用于您发行版的最新版本的 epel 和 remi。此链接适用于 Fedora 26

wget https://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
wget https://rpms.remirepo.net/fedora/remi-release-26.rpm

然后安装它们

rpm -Uvh remi-release-26.rpm
rpm -Uvh epel-release-6-8.noarch.rpm

现在您可以使用 remi 存储库来获取 php-pdo 和 php-mysql。

yum --enablerepo=remi install php-pdo
yum --enablerepo=remi install php-mysql

重新启动 Apache

systemctl stop httpd
systemctl start httpd

一切顺利!
Gerald Schneider
10 年前
本页建议常量 PDO::MYSQL_ATTR_FOUND_ROWS 始终可用(没有“从 X.X 版本开始存在”的说明),但我发现 PHP 5.2 安装中缺少此常量。在将 PHP 版本切换到 5.3.27 后,此常量在网页空间中可用。
To Top