RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
Visa 
4274 3200 2453 6495 

Глава 2. Обзор драйверов MySQL PHP

2.1. Введение

В зависимости от версии PHP, есть два или три API PHP для доступа к базе данных MySQL. PHP 5 может выбрать между устаревшим расширением mysql, mysqli или PDO_MySQL. PHP 7 удаляет расширение mysql, оставляя только последние два варианта.

Этот гид объясняет терминологию, используемую для описания каждыого API, информацию о выборе API, а также информацию, чтобы помочь выбрать, которую библиотеку применить с MySQL API.

2.2. Обзор терминологии

Эта секция обеспечивает введение в варианты, доступные вам, разрабатывая приложение PHP, которое должно взаимодействовать с базой данных MySQL.

Что такое API?

Application Programming Interface, API, определяет классы, методы, функции и переменные, которые должно будет вызвать ваше приложение, чтобы выполнить его желаемую задачу. В случае приложений PHP, которые должны общаться с базами данных, необходимый API обычно выставляется через расширения PHP.

API может быть процедурным или объектно-ориентированным. С процедурным API вы вызываете функции, чтобы выполнить задачи с объектно-ориентированным API, вы порождаете экземпляры классов и затем вызываете методы на полученных объектах. Последний обычно предпочтительный интерфейс, поскольку это более современно и приводит к лучше организованному коду.

Сочиняя приложения PHP, которые должны соединиться с сервером MySQL, есть несколько доступных вариантов API. Этот документ обсуждает то, что доступно и как выбрать лучшее решение для вашего приложения.

Что такое Connector?

В документации MySQL термин connector относится к части программного обеспечения, которое позволяет вашему приложению соединиться с сервером базы данных MySQL. MySQL обеспечивает соединители для множества языков, включая PHP.

Если ваше приложение PHP должно общаться с сервером базы данных, необходимо будет написать код, чтобы выполнить такие действия как соединение с сервером базы данных, запрос и другие связанные с базой данных функции. Программное обеспечение требуется, чтобы обеспечивать API, который ваше приложение будет использовать, а также обращаться со связью между вашим приложением и сервером базы данных, возможно пользуясь другими промежуточными библиотеками в случае необходимости. Это программное обеспечение известно в общем как соединитель, поскольку оно позволяет вашему приложению соединиться с сервером базы данных.

Что такое драйвер?

Драйвер это часть программного обеспечения, разработанного, чтобы общаться с определенным типом сервера базы данных. Драйвер может также вызвать библиотеку, такую как MySQL Client Library или MySQL Native Driver. Эти библиотеки осуществляют протокол низкого уровня, используемый, чтобы общаться с сервером базы данных MySQL.

Посредством примера уровень абстракции базы данных PHP Data Objects (PDO) может использовать один из нескольких определенных для базы данных драйверов. Один из драйверов, которых это имеет в наличии, является PDO MYSQL, который позволяет взаимодействовать с сервером MySQL.

Иногда люди используют термины "соединитель" и "драйвер" попеременно, это может быть запутывающим. В MySQL-связанной документации термин "драйвер" резервируется для программного обеспечения, которое обеспечивает определенную для базы данных часть пакета соединителя.

Что такое расширение?

В документации PHP вы столкнетесь с другим термином расширение. Код PHP состоит из ядра с дополнительными расширениями базовой функциональности. MySQL-связанные расширения PHP, например, mysqli и mysql осуществляются, используя дополнительную структуру PHP.

Расширение, как правило, выставляет API PHP программисту, чтобы позволить его средствам использоваться программно. Однако некоторые расширения, которые используют дополнительную структуру PHP, не выставляют API PHP программисту.

Расширение драйвера PDO MySQL, например, не выставляет API PHP программисту, но предоставляет интерфейс слою PDO выше его.

Термины "API" и "расширение" не должны быть применены, чтобы означать то же самое, так как расширение может не обязательно выставить API программисту.

2.3. Выбор API

PHP предлагает три различных API, чтобы соединиться с MySQL. Ниже мы показываем API, обеспеченные расширениями mysql, mysqli и PDO. Каждый фрагмент кода создает связь с сервером MySQL, работающим на "example.com", используя пользователя "user" и пароль "password".

Пример 2.1. Сравнения трех MySQL API

<?php
  // mysqli
  $mysqli = new mysqli("example.com", "user", "password", "database");
  $result = $mysqli->query("SELECT 'Hello, dear MySQL user!' AS _message FROM DUAL");
  $row = $result->fetch_assoc();
  echo htmlentities($row['_message']);

  // PDO
  $pdo = new PDO('mysql:host=example.com;dbname=database', 'user', 'password');
  $statement = $pdo->query("SELECT 'Hello, dear MySQL user!' AS _message FROM DUAL");
  $row = $statement->fetch(PDO::FETCH_ASSOC);
  echo htmlentities($row['_message']);

  // mysql
  $c = mysql_connect("example.com", "user", "password");
  mysql_select_db("database");
  $result = mysql_query("SELECT 'Hello, dear MySQL user!' AS _message FROM DUAL");
  $row = mysql_fetch_assoc($result);
  echo htmlentities($row['_message']);
?>

Рекомендуемый API

Рекомендуется использовать mysqli или PDO_MySQL. Не рекомендуется использовать старый mysql для новой разработки, поскольку это устарело в PHP 5.5.0 и было удалено в PHP 7. Подробная матрица сравнения особенности обеспечивается ниже. Общая производительность всех трех расширений считается равной. Выполнение расширения вносит только долю полного времени выполнения веб-запроса PHP. Часто воздействие всего 0.1%.

Сравнение особенности

ext/mysqli PDO_MySQLext/mysql
Введено в версии PHP5.0 5.12.0
Включено в PHP 5.xДаДа Да
Включено в PHP 7.xДаДа Нет
Статус разработкиActiveActive Обслуживание только в 5.x, удалено в 7.x
LifecycleActiveActive Устарело в 5.x, удалено в 7.x
Рекомендуемый для новых проектовДа ДаНет
Интерфейс OOPДаДаНет
Процедурный интерфейсДаНет Да
API поддерживает неблокирующие асинхронные запросы с mysqlndДаНетНет
Постоянные связиДаДа Да
API поддерживает CharsetsДаДа Да
API поддерживает подготовленные запросы на сервере ДаДаНет
API поддерживает подготовленные запросы на клиенте НетДаНет
API поддерживает хранимые процедурыДа ДаНет
API поддерживает мультизапросыДа MostНет
API поддерживает транзакцииДаДа Нет
Транзакциями можно управлять с SQLДа ДаДа
Поддержка полной функциональности MySQL 5.1+ ДаMostНет

2.4. Выбор библиотеки

Расширения mysqli, PDO_MySQL и mysql являются легкими обертками сверху библиотеки клиента C. Расширения могут пользоваться библиотекой mysqlnd или libmysqlclient. Выбор библиотеки является решением времени компиляции.

Библиотека mysqlnd часть дистрибутива PHP с версии 5.3.0. Это предлагает такие особенности, как ленивые связи и кэширование запроса, особенности, которые недоступны с libmysqlclient, так что применение mysqlnd очень рекомендовано. См. mysqlnd для дополнительных деталей и списка особенностей и функциональности, которые она предлагает.

Пример 2.2. Команды настройки для использования mysqlnd или libmysqlclient

// Recommended, compiles with mysqlnd
$ ./configure --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd \
              --with-mysql=mysqlnd
// Alternatively recommended, compiles with mysqlnd as of PHP 5.4
$ ./configure --with-mysqli --with-pdo-mysql --with-mysql
// Not recommended, compiles with libmysqlclient
$ ./configure --with-mysqli=/path/to/mysql_config \
              --with-pdo-mysql=/path/to/mysql_config \
              --with-mysql=/path/to/mysql_config

Сравнение возможностей библиотек

Рекомендуется пользоваться библиотекой mysqlnd вместо библиотеки MySQL Client Server (libmysqlclient). Обе библиотеки поддерживаются и постоянно улучшаются.

MySQL native driver (mysqlnd) Библиотека MySQL client server ( libmysqlclient)
Часть сборки PHPДа Нет
Введена в версии PHP 5.3.0N/A
ЛицензияPHP License 3.01 Dual-License
Статус разработкиActiveActive
LifecycleNo end announced No end announced
PHP 5.4 и выше, используется по умолчанию (для всех расширений MySQL)ДаНет
PHP 5.3, используется по умолчанию (для всех расширений MySQL)НетДа
Поддежка сжатого протоколаДа (5.3.1+) Да
Поддежка SSLДа (5.3.3+)Да
Поддежка именованных каналовДа (5.3.4+) Да
Да Нет
Исполнительная статистикаДаНет
LOAD LOCAL INFILE понимает директиву open_basedir directiveДаНет
Родная система управления памятью PHP например, следует лимитам памяти PHP)ДаНет
Возвратите числовую колонку как double (COM_QUERY) ДаНет
Возвратите числовую колонку как последовательность (COM_QUERY)ДаДа
Plugin APIДаLimited
Чтение-запись разделены для MySQL Replication Да с плагиномНет
Выравнивание нагрузкиДа с плагином Нет
Fail overДа с плагиномНет
Ленивые связиДа с плагином Нет
Кэширование запросаДа с плагином Нет
Прозрачные манипуляции запроса (например, auto-EXPLAIN или мониторинг)Да с плагиномНет
Автоматическое пересоединениеНет Опционально

2.5. Концепции

Эти понятия определены для драйверов MySQL для PHP.

2.5.1. Буферизованные и небуферизированные запросы

Запросы используют буферизированный способ по умолчанию. Это означает, что результаты запроса немедленно передаются от MySQL Server в PHP и затем сохранены в памяти PHP. Это позволяет такие дополнительные операции, как подсчет количества строк и перемещения указателя текущего результата. Это также позволяет выпускать дальнейшие запросы на той же самой связи, работая над набором результатов. Оборотная сторона буферизированного способа то, что большие наборы результатов могли бы потребовать довольно большой памяти. Память будет сохранена занятой, пока все ссылки на набор результатов не будут сброшены, или набор результатов не будет явно освобожден, что автоматически произойдет во время конца запроса. Терминология "хранение результата" также используется для буферизированного способа, поскольку набор результатов сохранен сразу.

Используя libmysqlclient как библиотеку, предел памяти PHP не посчитает память используемой для наборов результатов, если данные не будут принесены в переменные PHP. С mysqlnd память будет включать полный набор результатов.

Небуферизированные запросы MySQL выполняют запрос и затем возвращают ресурс в то время как данные все еще ждут на сервере MySQL. Это использует меньше памяти на PHP-стороне, но может увеличить нагрузку на сервере. Если полный набор результатов не был принесен от сервера, никакие дальнейшие запросы нельзя послать по той же самой связи. Небуферизированные запросы могут также упоминаться как "использование результата".

Буферизованные запросы должны использоваться в случаях, где вы ожидаете только ограниченный набор результатов или должны знать сумму возвращенных строк прежде, чем прочитать все строки. Небуферизированный способ должен использоваться, когда вы ожидаете большие результаты.

Поскольку буферизированные запросы являются умолчанием, примеры ниже продемонстрируют, как выполнить небуферизированные запросы с каждым API.

Пример 2.3. Пример небуферизированного запроса: mysqli

<?php
  $mysqli= new mysqli("localhost", "my_user", "my_password", "world");
  $uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT);
  if ($uresult)
  {
     while ($row = $uresult->fetch_assoc())
     {
       echo $row['Name'] . PHP_EOL;
     }
  }
  $uresult->close();
?>

Пример 2.4. Пример небуферизированного запроса: pdo_mysql

<?php
  $pdo = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_pass');
  $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
  $uresult = $pdo->query("SELECT Name FROM City");
  if ($uresult)
  {
     while ($row = $uresult->fetch(PDO::FETCH_ASSOC))
     {
       echo $row['Name'] . PHP_EOL;
     }
  }
?>

Пример 2.5. Пример небуферизированного запроса: mysql

<?php
  $conn = mysql_connect("localhost", "my_user", "my_pass");
  $db = mysql_select_db("world");
  $uresult = mysql_unbuffered_query("SELECT Name FROM City");
  if ($uresult)
  {
     while ($row = mysql_fetch_assoc($uresult))
     {
       echo $row['Name'] . PHP_EOL;
     }
  }
?>

2.5.2. Наборы символов

Идеально надлежащий набор символов будет установлен на уровне сервера, выполнение этого описано в разделе Character Set Configuration в руководстве на MySQL Server. Альтернативно, каждый MySQL API предлагает метод, чтобы установить набор символов во время выполнения.

Набор символов должен быть понят и определен, поскольку он имеет влияние на каждом действии и включает последствия безопасности. Например, экранировка (например, mysqli_real_escape_string в mysqli, mysql_real_escape_string в mysql и PDO::quote в PDO_MySQL) будет придерживаться этой настройки. Важно понять, что эти функции не будут использовать набор символов, который определяется с запросом, таким образом, например, следующее не будет иметь эффекта:

Пример 2.6. Проблемы с урегулированием набора символов с SQL

<?php
  $mysqli = new mysqli("localhost", "my_user", "my_password", "world");
  // Will NOT affect $mysqli->real_escape_string();
  $mysqli->query("SET NAMES utf8");
  // Will NOT affect $mysqli->real_escape_string();
  $mysqli->query("SET CHARACTER SET utf8");
  // But, this will affect $mysqli->real_escape_string();
  $mysqli->set_charset('utf8');
  // But, this will NOT affect it (utf-8 vs utf8) -- don't use dashes here
  $mysqli->set_charset('utf-8');
?>

Ниже даны примеры, которые демонстрируют, как правильно изменить набор символов во время выполнения, используя каждый API.

Поскольку имена наборов символов в MySQL не содержат тире, последовательность "utf8" действительна в MySQL, чтобы установить набор символов в UTF-8. Последовательность "utf-8" не действительна, поскольку использование "utf-8" не изменит набор символов.

Пример 2.7. Установка набора символов: mysqli

<?php
  $mysqli = new mysqli("localhost", "my_user", "my_password", "world");
  printf("Initial character set: %s\n", $mysqli->character_set_name());
  if (!$mysqli->set_charset('utf8'))
  {
     printf("Error loading character set utf8: %s\n", $mysqli->error);
     exit;
  }
  echo "New character set information:\n";
  print_r($mysqli->get_charset());
?>

Пример 2.8. Установка набора символов: pdo_mysql

Примечание: Это работает только с PHP 5.3.6.

<?php
  $pdo = new PDO("mysql:host=localhost;dbname=world;charset=utf8", 'my_user', 'my_pass');
?>

Пример 2.9. Установка набора символов: mysql

<?php
  $conn = mysql_connect("localhost", "my_user", "my_pass");
  $db = mysql_select_db("world");
  echo 'Initial character set: ' .mysql_client_encoding($conn) . "\n";
  if (!mysql_set_charset('utf8', $conn))
  {
     echo "Error: Unable to set the character set.\n";
     exit;
  }
  echo 'Your current character set is: ' .mysql_client_encoding($conn);
?>

Поиск

 

Найди своих коллег!

Вы можете направить письмо администратору этой странички, Алексею Паутову. mailto:alexey.v.pautov@mail.ru