PHP 8.3.4 Released!

MySQL 関数 (PDO_MYSQL)

はじめに

PDO_MYSQL は、PHP から MySQL データベースへのアクセスを可能にするための PHP Data Objects (PDO) インターフェイス を実装したドライバです。

PDO_MYSQLは、 デフォルトでエミュレートされたプリペアドステートメントを使います。

MySQL 8

PHP 7.1.16 より前のバージョン、もしくは PHP 7.2.4 より前の 7.2系の PHP では、 MySQL 8 サーバーのデフォルトパスワードプラグインを mysql_native_password に設定するようにしてください。 さもないと、 The server requested authentication method unknown to the client [caching_sha2_password] のようなエラーを見ることになります。たとえあなたが caching_sha2_password を使っていなくても、です。

これは MySQL 8 のデフォルトが 古い PHP (mysqlnd) のリリースが認識していないプラグイン caching_sha2_password だからです。 かわりに、my.cnf の設定を default_authentication_plugin=mysql_native_password と変更してください。 caching_sha2_password プラグインは、 PHP 7.4.4 以降で完全にサポートされました。 これより前のバージョンでは、 mysql_xdevapi 拡張モジュールでサポートされています。

警告

注意: MySQL のテーブル型 (ストレージエンジン) の中には、 トランザクションをサポートしていないものがあります。 トランザクションをサポートしていないテーブル型を使用して トランザクションを使用するコードを書くと、 MySQL はトランザクションが正常に使用できたかのように振舞います。 さらに、DDL クエリを実行する際には、 実行中のトランザクションが暗黙的にコミットされます。

注意:

MySQL ドライバは、 PDOStatement::bindParam() メソッドで PDO::PARAM_INPUT_OUTPUT を適切にサポートしていません。使うことはできますが、 値が更新されません。(つまり、出力が無視されています)

インストール手順

一般的な Unix ディストリビューションには、バイナリ版の PHP がインストールされています。 これらのバイナリ版は、通常は MySQL 拡張モジュールを有効にしてビルドされています。 しかし、拡張モジュールのライブラリ自身を別パッケージでインストールする必要があるでしょう。 使用しているディストリビューションのパッケージマネージャで確認してみましょう。

たとえば Ubuntu なら、php5-mysql パッケージをインストールすれば、 ext/mysql、ext/mysqli、そして pdo_mysql をインストールできます。CentOS の場合は php-mysql パッケージを使えば、同じものをインストールできます。

この拡張モジュールを自分でコンパイルすることもできます。 PHP をソースからビルドすれば、使いたい MySQL 拡張モジュールを指定したり 各拡張モジュールが使用するクライアントライブラリを選択したりすることができます。

--with-pdo-mysql[=DIR] で PDO MySQL 拡張モジュールをインストールします。オプションの [=DIR] は、MySQL ベースライブラリの場所です。 Mysqlnd がデフォルトのベースライブラリです。 どのライブラリを選べばいいのかについての詳細は MySQL ライブラリの選択 を参照ください。

オプションの --with-mysql-sock[=DIR] で MySQL unix ソケットの場所を指定することができます。これは PDO_MYSQL を含むすべての MySQL 拡張モジュールで利用します。省略した場合はデフォルトの場所を検索します。

オプションの --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() をコールするのと同じ意味になります。また、SSL を PDO::setAttribute で有効にすることはできません。というのも、この時点ではすでに接続が確立されてしまっているからです。 MySQL のドキュメントで » SSL を使った MySQL への接続 について確認しましょう。

定義済み定数

このドライバでは以下の定数が定義されて います。これは拡張モジュールが PHP に組み込まれているか、実行時に動的にロード されている場合のみ使用可能です。さらに、これらのドライバ固有の定数は そのドライバを使用している場合にのみ使用されます。 あるドライバ固有の属性を別のドライバで使うと、予期せぬ結果を引き起こします。 もし複数のドライバを使用しているコードを実行している場合、 PDO::getAttribute()PDO::ATTR_DRIVER_NAME 属性を使用することで、使用中のドライバ名を調べることが可能です。

PDO::MYSQL_ATTR_USE_BUFFERED_QUERY (bool)
デフォルトでは、全てのステートメントが バッファモード. で実行されます。 この値を false に設定すると、 PDO オブジェクトの場合、 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認証局の証明書が入ったディレクトリパス。 証明書は、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 ドメインソケットを設定します。 configure の際にドメインソケットが見つかれば、 この値はコンパイル時にも設定されます。この ini 設定は Unix でのみ使えます。

pdo_mysql.debug bool

PDO_MYSQL のデバッグ機能を有効にします。 この設定が有効になるのは、mysqlnd を使って PDO_MYSQL をでコンパイルし、 かつ PDO がデバッグモードであるときだけです。

目次

add a note

User Contributed Notes 8 notes

up
13
Desislav Kamenov
6 years ago
There is an important undocumented attribute which disables certificate CN verification available after
5.6.22 (not sure), 7.0.18 (verified) and 7.1.15 (not sure)

PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT

possible values: true, false
default value: true

Related PHP bugs:
https://bugs.php.net/bug.php?id=71845
https://bugs.php.net/bug.php?id=71003

and github PR: https://github.com/php/php-src/pull/1913
up
7
brian at diamondsea dot com
15 years ago
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. ...

After spending hours trying to track down why we were getting this error on a new server, after the same code ran fine on other servers, we found the problem to be an old MySQL _client_ library running on our web server, and a latest-version MySQL _server_ running on the database server's box.

Upgraded the MySQL client on the web server to the current revision and the problem went away.
up
6
davey at php dot net
16 years ago
To use "PDO::MYSQL_ATTR_USE_BUFFERED_QUERY" you should call
PDO::setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);

It will not work when passed into PDO::prepare()
up
4
curt at webmasterbond dot com
12 years ago
Today's PHP snapshot now has SSL support for PDO. Follow the directions here ( http://dev.mysql.com/doc/refman/5.0/en/secure-create-certs.html ) to set up MySQL and then use the following connection options:

<?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'
)
);
?>
up
-3
rmottey at gmail dot com
16 years ago
I have been getting the error below when performing multiple queries within a single page.

Setting the attribute below did not seem to work for me.

So building on previous example i am initilizing my stmt variable on every query and a fetch all into an array. Seems to be working for me.

Error:
PDO Error 1.1: Array ( [0] => xxx[1] => yyy[2] => Lost connection to MySQL server during query )

Fix:

(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()");

// call the stored procedure
$stmt->execute();
// fetch all rows into an array.
$rows = $stmt->fetchAll();
foreach ($rows as $rs)
{
$id = $rs['id'];
}
//initilise the statement
unset($stmt);
$stmt = $dbh->prepare("call secondprocedure(?);");
$stmt->bindValue(1, $id);
if ( ! $stmt->execute() )
{
echo "PDO Error 1.1:\n";
print_r($stmt->errorInfo());
exit;
}
unset($stmt);
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
?>
up
-6
miller_kurt_e at yahoo dot com
15 years ago
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. ...

This one can be a royal pain to deal with. Never stack statements to be executed in one go. Nobody ever mentions this possibility in all the posts I've seen dealing with this error.

This example is a Zend Framework example but the theory is the same.

As in:

<?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);
?>

This will run fine but PDO will balk with the 'unbuffered' error if you follow this with another query.

Instead do:

<?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);
?>

Chopping it into individual queries fixes the problem.
up
-10
vafa ghoreyshi atgmailcom
6 years ago
If you have the error 'could not find driver' and won't able to install driver for newer linux(Fedora, Redhat, CentOS) with latest PHP7/MariaDB10/Apache2.4 get this package installed and get every things smooth.
First download latest version of epel and remi for your distribution. This links is for 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

Than install them

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

Know you can use remi repository to gest php-pdo and php-mysql.

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

Restart the Apache

systemctl stop httpd
systemctl start httpd

Good to go!
up
-44
Gerald Schneider
10 years ago
This page suggests that the constant PDO::MYSQL_ATTR_FOUND_ROWS was always available (no note "exists as of X.X"), but I found the constant missing on an installation with PHP 5.2. After switching the PHP version to 5.3.27 on the webspace the constant was available.
To Top