Как стать автором
Поиск
Написать публикацию
Обновить

PHP: работа с реплицированными mysql-серверами

Этот топик основан на советах, полученных от русского сообщества Zendframework и поисков по мануалам php.

Появилась достаточно интересная задача: в наличии два реплицированных сервера mysql: master и slave. Изменения на сервере master копируются в slave. Необходимо правильно организовать работу с базой данных, чтобы для программиста ее использование осталось максимально прозрачным (например, текущие интерфейсы классов библиотеки Zend не изменились), а разные типы запросов попадали на разные сервера.

Имеется в виду, что изменения данных (например, update) должны вестись с сервером master, а выборка (например, select) с сервера slave.

Репликация сама по себе повышает доступность данных и увеличивает надежность их хранения.

image

В php существует возможность работы с несколькими соединениями с базой путем определения их идентификаторов. Таким образом первое подходящее решение — замена стандартной функции mysql_query(string $query) более общей, с парсингом строки запроса.

Итак, создаем два подключения:
$master_db_server = mysql_connect(DB_HOST_MASTER, DB_USER_MASTER, DB_PASS_MASTER, true) or sqlErrorHandler(mysql_errno(), mysql_error(), mysql_stat(), __FILE__, __LINE__);
$slave_db_server = mysql_connect(DB_HOST_SLAVE, DB_USER_SLAVE, DB_PASS_SLAVE, true) or sqlErrorHandler(mysql_errno(), mysql_error(), mysql_stat(), __FILE__, __LINE__);


Соответственно дальше можно отправлять нужные запросы к нужному подключению, например:
mysql_query($query_line, $master_db_server);

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

Похожее решение реализовано в виде дополнительного класса к библиотеке Zend. Помимо распределения запросов между нужным количество серверов, возможно принудительное переключение на использование только Master или Slave-сервера.

Третьим возможным решением становится использование улучшенного mysql в php. Расширение mysqli позволяет использовать возможности MySQL версий 4.1 и выше. В них входит использование транзакций и поддержка реплицированных серверов. При этом работа с функциями mysqli не сильно отличается от работы со стандартным mysql:

<?php

/* Connect to a MySQL server */
$mysqli = new mysqli(’localhost’, ’user’, ’password’, ’world’);

if (mysqli_connect_errno()) {
printf(«Can’t connect to MySQL Server. Errorcode: %s\n», mysqli_connect_error());
exit;
}

/* Send a query to the server */
if ($result = $mysqli->query(’SELECT Name, Population FROM City ORDER BY Population DESC LIMIT 5’)) {

print(«Very large cities are:\n»);

/* Fetch the results of the query */
while( $row = $result->fetch_assoc() ){
printf(«%s (%s)\n», $row[’Name’], $row[’Population’]);
}

/* Destroy the result set and free the memory used for it */
$result->close();
}

/* Close the connection */
$mysqli->close();
?>


Zend Framework также может использовать адаптер MySQLi, но мануал описывает нюансы в его использовании:
  • Для установки этого адаптера через метод factory() используется строка ’Mysqli’.
  • Этот адаптер использует PHP-расширение mysqli (что очевидно).
  • MySQL не поддерживает последовательности, поэтому lastInsertId() игнорирует переданные аргументы и всегда возвращает последнее значение, сгенерированное для автоинкрементного ключа. Метод lastSequenceId() возвращает NULL.

Итак, мы получили три пути решения для различных типов приложений. На мой взгляд наиболее рациональным является использование MySQLi адаптера в Zend Framework.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.