CakeFest 2024: The Official CakePHP Conference

Функции MySQL (PDO_MYSQL)

Введение

PDO_MYSQL — это драйвер, который реализует интерфейс PHP Data Objects (PDO) и даёт PHP доступ к базам данных MySQL.

Драйвер PDO_MYSQL по умолчанию использует эмулированную подготовку.

MySQL 8

При запуске PHP до версии 7.1.16 или PHP с версии 7.2 до версии 7.2.4 в качестве плагина шифрования паролей по умолчанию для сервера MySQL 8 устанавливают mysql_native_password, иначе будет выдана ошибка наподобие The server requested authentication method unknown to the client [caching_sha2_password], даже когда плагин caching_sha2_password не задан.

Причина этого в том, что на сервере MySQL 8 в качестве плагина по умолчанию указан caching_sha2_password, который не распознаётся старыми версиями PHP (модулем mysqlnd). Вместо него в файле конфигурации сервера my.cnf указывают — default_authentication_plugin=mysql_native_password. Плагин caching_sha2_password получил полную поддержку начиная с PHP 7.4.4. В предыдущих версиях PHP его поддерживает модуль mysql_xdevapi.

Внимание

Осторожно: MySQL-таблицы подсистемы хранения данных не поддерживают транзакции. Если в коде, который работает с транзакционной базой данных, указана неподдерживающая транзакции таблица, MySQL сделает вид, что транзакция успешно начата. И ещё, каждый выполненный DDL-запрос будет неявно фиксировать незавершённые транзакции — то есть завершать открытые транзакции и выполнять стек незавершённых запросов.

Замечание:

Драйвер MySQL неправильно обрабатывает бит PDO::PARAM_INPUT_OUTPUT в методе PDOStatement::bindParam(); хотя такие параметры и разрешено использовать, они не обновляются (т. е. фактический вывод игнорируется).

Установка

Обычно установочные пакеты 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] указывает расположение unix-сокета MySQL для всех MySQL модулей, включая PDO_MYSQL. Если параметр не указан, поиск производится в директориях по умолчанию.

Дополнительный параметр --with-zlib-dir[=DIR] используется как префикс пути к libz.

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

Поддержка SSL включается, используя соответствующую константу PDO_MySQL, которая эквивалентна вызову » API MySQL-функции mysql_ssl_set() в C. К тому же SSL не может быть включён с помощью PDO::setAttribute, потому что соединение уже существует. Смотрите документацию MySQL о » подключении к MySQL с SSL.

Предопределённые константы

Драйвер определяет перечисленные ниже константы, которые доступны только тогда, когда PHP собрали с поддержкой этого модуля, или модуль динамически загрузили во время исполнения кода. Зависимые от драйвера константы разрешно использовать только совместно с этим драйвером. Атрибуты одного драйвера с другим драйвером ведут себя неожиданно. Для проверки названия драйвера, которое содержит атрибут PDO::ATTR_DRIVER_NAME, вызывают метод PDO::getAttribute(), если код запускается с несколькими драйверами.

PDO::MYSQL_ATTR_USE_BUFFERED_QUERY (bool)
По умолчанию запросы выполняются в буферизованном режиме. Драйвер MySQL будет использовать небуферизованный режим, если для объекта PDO значение этого атрибута установить как false.

Пример #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 Мб. Эта константа не поддерживается при компиляции вместе с 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. Эту опцию необходимо указать во время компиляции, если сокет домена найден во время конфигурирования. Эта настройка только для Unix.

pdo_mysql.debug bool

Разрешает отладку для PDO_MYSQL. Эта настройка доступна только, если PDO_MYSQL скомпилирован с "mysqlnd" и в режиме отладки PDO.

Содержание

  • PDO_MYSQL DSN — Соединение с базой данных MySQL
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