|
Spec-Zone .ru
спецификации, руководства, описания, API
|
Copyright 1997-2012 PHP Documentation Group.
Плагин кэша запроса mysqlnd удобен. Этот быстрый запуск будет демонстрационные типичные примеры использования, и обеспечивать практический совет относительно начинания.
Строго рекомендуется считать ссылочные разделы в дополнение к быстрому запуску. Безопасно начаться с быстрого запуска. Однако, перед использованием плагина в миссии критические среды мы убеждаем Вас считать дополнительно вводную информацию из ссылочных разделов.
Большинство примеров использует mysqli расширение, потому что это - полное расширение MySQL PHP большинства функции. Однако, плагин может использоваться с любым расширением MySQL PHP, которое пользуется mysqlnd библиотекой.
Copyright 1997-2012 PHP Documentation Group.
Плагин кэша запроса реализуется как расширение PHP. Это пишется в C и работает под капотом PHP. Во время запуска интерпретатора PHP это регистрируется как mysqlnd плагин, чтобы заменить выбранные mysqlnd методы C. Тем самым это может изменить поведение любого расширения MySQL PHP (mysqli, PDO_MYSQL, mysql) скомпилированный, чтобы пользоваться mysqlnd библиотекой, не изменяя API расширений. Это делает плагин совместимым с каждым приложением MySQL PHP. Поскольку существующие API не изменяются, это почти прозрачно, чтобы использовать. Пожалуйста, см. mysqlnd сменное описание API для обсуждения преимуществ сменной архитектуры и сравнения с прокси базируемые решения.
Прозрачный, чтобы использовать
Во время выполнения PHP PECL/mysqlnd_qc может проксировать запросы, передаются от PHP (mysqlnd) к серверу MySQL. Это тогда осматривает строку оператора, чтобы найти, должно ли это кэшировать свои результаты. Если так, набор результатов кэшируется, используя обработчик хранения, и дальнейшее выполнение оператора подается от кэша в течение определяемого пользователем периода. Время, чтобы Жить (TTL) записи кэша может или быть установлено глобально или на на основание оператора.
Оператор или кэшируется, если плагин проинструктирован, чтобы кэшировать все операторы, глобально используя
a или, если строка запроса запускается с подсказки SQL (/*qc=on*/). Плагин
способен к кэшированию любого запроса, выпущенного, вызывая соответствующие вызовы API любого из
существующих расширений MySQL PHP.
Гибкое хранение: различный обработчик хранения
Различный обработчик хранения поддерживается, чтобы предложить различные контексты для записей кэша. Различные контексты учитывают различные градусы в совместном использовании записей кэша среди клиентов.
default (встроенный): память процесса, контекст:
процесс, один или более веб-запросов в зависимости от модели развертывания PHP используются
APC: разделяемая память, контекст: единственный
сервер, многократные веб-запросы
SQLite: память или файл, контекст: единственный
сервер, многократные веб-запросы
MEMCACHE: оперативная память, контекст:
единственный или многократный сервер, многократные веб-запросы
user (встроенный): определяемый пользователем -
любой, контекст: определяемый пользователем - любой
Поддержка APC, SQLite и
MEMCACHE обработчик хранения должен быть включен во время компиляции.
default и user обработчик встроен. Возможно переключиться между
скомпилированным - в обработчиках хранения на на основание запроса во время выполнения. Однако,
рекомендуется выбрать один обработчик хранения и использовать это для всех записей кэша.
Встроенная защита хлопка, чтобы избежать перегружаться
Чтобы избежать ситуаций с перегрузкой, у плагина кэша есть встроенный защитный механизм хлопка. Если популярный кэш, записи истекают много клиентов, использующих записи кэша, попытается обновить запись кэша. Для продолжительности обновления много клиентов могут получить доступ к серверу базы данных одновременно. В худшем случае сервер базы данных становится перегруженным, и требуется все больше времени, чтобы обновить запись кэша, которая поочередно позволяет все большему количеству клиентов пытаться обновить запись кэша. Чтобы препятствовать тому, чтобы это произошло, у плагина есть защитный механизм хлопка. Если защита хлопка включается, и плагин обнаруживает запись кэша с истекшим сроком, это расширяет время жизни записи кэша прежде, чем это обновит запись кэша. Этим путем другие параллельные доступы к записи кэша с истекшим сроком все еще подаются от кэша в течение определенного времени. Другие параллельные доступы, чтобы не инициировать параллельное обновление. Идеально, запись кэша обновляется клиентом, который расширял продолжительность жизни записей кэша прежде, чем другие клиенты попытаются обновить кэш и потенциально вызвать ситуацию с перегрузкой.
Уникальный подход к кэшированию
У PECL/mysqlnd_qc есть уникальный подход к кэшированию наборов результатов, который превосходит приложение базируемые решения для кэша. Приложение базируемые решения сначала выбирает набор результатов в переменные PHP. Затем, переменные PHP сериализируются для хранения в персистентном кэше, и затем несериализируются, выбирая. Кэш запроса mysqlnd хранит необработанные проводные данные протокола, отправленные от MySQL до PHP в его кэше, и воспроизводит это, если все еще допустимый, на удачном обращении в кэш. Таким образом, это сохраняет дополнительный шаг сериализации для кэша, помещенного, который должно сделать все приложение базируемые решения. Это может хранить необработанные проводные данные протокола в кэше, не имея необходимость сериализировать в переменную PHP сначала и десериализовывая переменную PHP для того, чтобы сохранить в кэше снова.
Copyright 1997-2012 PHP Documentation Group.
Плагин реализуется как расширение PHP. См. также инструкции по установке, чтобы установить расширение .
Скомпилируйте или сконфигурируйте расширение MySQL PHP (mysqli, PDO_MYSQL, mysql), что Вы планируете использовать с поддержкой mysqlnd библиотеки. PECL/mysqlnd_qc является плагином для mysqlnd библиотеки. Чтобы использовать плагин с любым из существующих расширений MySQL PHP (API), расширение должно пользоваться mysqlnd библиотекой.
Затем, загрузите расширение в PHP и активируйте плагин в конфигурационном файле PHP, используя конфигурационную директиву PHP, названную mysqlnd_qc.enable_qc.
Copyright 1997-2012 PHP Documentation Group.
Есть четыре способа инициировать кэширование запроса.
mysqlnd_qc.cache_by_default
= 1 кэшировать все запросы вслепую
Использование SQL подсказывает и mysqlnd_qc.cache_by_default
= 1 объясняются ниже. Пожалуйста, обратитесь к функциональной ссылке на для описания использования обратного вызова и, mysqlnd_qc_set_cache_condition о том, как установить правила для
автоматического кэширования.
Подсказка SQL является SQL стандарты совместимый комментарий. Как комментарий SQL это игнорируется базой
данных. Оператор считают имеющим право на кэширование, если он или начинается с кэширования включения
подсказки SQL, или это - a SELECT оператор.
Отдельный запрос, который должен кэшироваться, должен начаться с подсказки SQL /*qc=on*/.
Рекомендуется использовать константу PHP MYSQLND_QC_ENABLE_SWITCH
вместо того, чтобы использовать строковое значение.
не имеющий право на кэширование и не кэшируемый: INSERT
INTO test(id) VALUES (1)
не имеющий право на кэширование и не кэшируемый: SHOW
ENGINES
имеющий право на кэширование, но некэшируемый: SELECT id
FROM test
имеющий право на кэширование и кэшируемый: /*qc=on*/SELECT
id FROM test
Примеры SELECT строка оператора снабжается префиксом MYSQLND_QC_ENABLE_SWITCH Подсказка SQL, чтобы
позволить кэшироваться оператора. Подсказка SQL должна быть дана в самом начале строки оператора позволить
кэшироваться.
Пример 22.308. Используя MYSQLND_QC_ENABLE_SWITCH Подсказка
SQL
mysqlnd_qc.enable_qc=1
<?php/* Connect, create and populate test table */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id INT)");$mysqli->query("INSERT INTO test(id) VALUES (1), (2)");/* Will be cached because of the SQL hint */$start = microtime(true);$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 1");var_dump($res->fetch_assoc());$res->free();printf("Total time uncached query: %.6fs\n", microtime(true) - $start);/* Cache hit */$start = microtime(true);$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 1");var_dump($res->fetch_assoc());$res->free();printf("Total time cached query: %.6fs\n", microtime(true) - $start);?>
Вышеупомянутые примеры выведут что-то подобное:
array(1) { ["id"]=> string(1) "1"}Total time uncached query: 0.000740sarray(1) { ["id"]=> string(1) "1"}Total time cached query: 0.000098s
Если ничто иное не будет сконфигурировано, поскольку это имеет место в примере быстрого запуска, то плагин
будет использовать встроенное default обработчик хранения. default обработчик хранения использует память процесса, чтобы содержать
запись кэша. В зависимости от модели развертывания PHP процесс PHP может служить одному или более
веб-запросам. Пожалуйста, консультируйтесь с руководством веб-сервера для деталей. Детали не имеют никакого
значения для примеров, данных в быстром запуске.
Плагин кэша запроса будет кэшировать все запросы независимо, если строка запроса начнется с подсказки SQL,
которая позволяет кэшироваться или нет, если конфигурационная директива PHP mysqlnd_qc.cache_by_default устанавливается в
1. Установка mysqlnd_qc.cache_by_default
оценивается ядром плагинов кэша запроса. Ни встроенный ни определяемый пользователем обработчик хранения не
может отвергнуть установку.
Подсказка SQL /*qc=off*/ может использоваться, чтобы отключить кэширование
отдельных запросов если mysqlnd_qc.cache_by_default
= 1 Рекомендуется использовать константу PHP MYSQLND_QC_DISABLE_SWITCH
вместо того, чтобы использовать строковое значение.
Пример 22.309. Используя MYSQLND_QC_DISABLE_SWITCH
Подсказка SQL
mysqlnd_qc.enable_qc=1mysqlnd_qc.cache_by_default=1
<?php/* Connect, create and populate test table */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id INT)");$mysqli->query("INSERT INTO test(id) VALUES (1), (2)");/* Will be cached although no SQL hint is present because of mysqlnd_qc.cache_by_default = 1*/$res = $mysqli->query("SELECT id FROM test WHERE id = 1");var_dump($res->fetch_assoc());$res->free();$mysqli->query("DELETE FROM test WHERE id = 1");/* Cache hit - no automatic invalidation and still valid! */$res = $mysqli->query("SELECT id FROM test WHERE id = 1");var_dump($res->fetch_assoc());$res->free();/* Cache miss - query must not be cached because of the SQL hint */$res = $mysqli->query("/*" . MYSQLND_QC_DISABLE_SWITCH . "*/SELECT id FROM test WHERE id = 1");var_dump($res->fetch_assoc());$res->free();?>
Вышеупомянутые примеры выведут:
array(1) { ["id"]=> string(1) "1"}array(1) { ["id"]=> string(1) "1"}NULL
PECL/mysqlnd_qc запрещает кэширование операторов, для которых по крайней мере один столбец от набора
результатов операторов не показывает имени таблицы в своих метаданных по умолчанию. Это обычно имеет место
для столбцов, происходящих из функций SQL такой как NOW() или LAST_INSERT_ID(). Политика стремится предотвращать ловушки, если кэширование
по умолчанию используется.
Пример 22.310. Пример, показывающий, какой тип операторов не кэшируется
mysqlnd_qc.enable_qc=1mysqlnd_qc.cache_by_default=1
<?php/* Connect, create and populate test table */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id INT)");$mysqli->query("INSERT INTO test(id) VALUES (1)");for ($i = 0; $i < 3; $i++) { $start = microtime(true); /* Note: statement will not be cached because of NOW() use */ $res = $mysqli->query("SELECT id, NOW() AS _time FROM test"); $row = $res->fetch_assoc(); /* dump results */ var_dump($row); printf("Total time: %.6fs\n", microtime(true) - $start); /* pause one second */ sleep(1);}?>
Вышеупомянутые примеры выведут что-то подобное:
array(2) { ["id"]=> string(1) "1" ["_time"]=> string(19) "2012-01-11 15:43:10"}Total time: 0.000540sarray(2) { ["id"]=> string(1) "1" ["_time"]=> string(19) "2012-01-11 15:43:11"}Total time: 0.000555sarray(2) { ["id"]=> string(1) "1" ["_time"]=> string(19) "2012-01-11 15:43:12"}Total time: 0.000549s
Возможно позволить кэшироваться для всех операторов включая тех, у которого есть столбцы в их наборе
результатов, для которого MySQL не сообщает ни о какой таблице, такой как оператор от примера. Набор mysqlnd_qc.cache_no_table = 1 позволять кэшироваться таких операторов.
Пожалуйста, отметьте различие в измеренные времена для вышеупомянутого и ниже примеров.
Пример 22.311. Включение кэширующийся для всех операторов, используяmysqlnd_qc.cache_no_table установка ini
mysqlnd_qc.enable_qc=1mysqlnd_qc.cache_by_default=1mysqlnd_qc.cache_no_table=1
<?php/* Connect, create and populate test table */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id INT)");$mysqli->query("INSERT INTO test(id) VALUES (1)");for ($i = 0; $i < 3; $i++) { $start = microtime(true); /* Note: statement will not be cached because of NOW() use */ $res = $mysqli->query("SELECT id, NOW() AS _time FROM test"); $row = $res->fetch_assoc(); /* dump results */ var_dump($row); printf("Total time: %.6fs\n", microtime(true) - $start); /* pause one second */ sleep(1);}?>
Вышеупомянутые примеры выведут что-то подобное:
array(2) { ["id"]=> string(1) "1" ["_time"]=> string(19) "2012-01-11 15:47:45"}Total time: 0.000546sarray(2) { ["id"]=> string(1) "1" ["_time"]=> string(19) "2012-01-11 15:47:45"}Total time: 0.000187sarray(2) { ["id"]=> string(1) "1" ["_time"]=> string(19) "2012-01-11 15:47:45"}Total time: 0.000167s
Хотя mysqlnd_qc.cache_no_table = 1 был создан для использования с mysqlnd_qc.cache_by_default =
1 это связывается это. Плагин оценит mysqlnd_qc.cache_no_table всякий раз, когда запрос должен кэшироваться,
независимо от того было ли кэширование включено, используя подсказку SQL или какую-либо другую меру.
Copyright 1997-2012 PHP Documentation Group.
Стратегия аннулирования значения по умолчанию плагина кэша запроса пора Жить (TTL). Встроенные обработчики хранения будут использовать значение по умолчанию
TTL определенный значением конфигурации PHP mysqlnd_qc.ttl если строка запроса не содержит
подсказку для того, чтобы установить различное TTL. TTL определяется в секундах. Значением по умолчанию записи кэша истекают
после 30 секунды
Наборы в качестве примера mysqlnd_qc.ttl=3 к операторам кэша в течение трех
секунд по умолчанию. Каждую секунду это обновляет запись таблицы базы данных, чтобы содержать текущее время
и выполняет a SELECT оператор, чтобы выбрать запись от базы данных. SELECT оператор кэшируется в течение трех секунд, потому что он снабжается
префиксом кэширование включения подсказки SQL. Вывод проверяет, что результаты запроса берутся от кэша для
продолжительности трех секунд прежде, чем они будут обновлены.
Пример 22.312. Установка TTL с mysqlnd_qc.ttl установка ini
mysqlnd_qc.enable_qc=1mysqlnd_qc.ttl=3
<?php/* Connect, create and populate test table */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id VARCHAR(255))");for ($i = 0; $i < 7; $i++) { /* update DB row */ if (!$mysqli->query("DELETE FROM test") || !$mysqli->query("INSERT INTO test(id) VALUES (NOW())")) /* Of course, a real-life script should do better error handling */ die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error)); /* select latest row but cache results */ $query = "/*" . MYSQLND_QC_ENABLE_SWITCH . "*/"; $query .= "SELECT id AS _time FROM test"; if (!($res = $mysqli->query($query)) || !($row = $res->fetch_assoc())) { printf("[%d] %s\n", $mysqli->errno, $mysqli->error); } $res->free(); printf("Wall time %s - DB row time %s\n", date("H:i:s"), $row['_time']); /* pause one second */ sleep(1);}?>
Вышеупомянутые примеры выведут что-то подобное:
Wall time 14:55:59 - DB row time 2012-01-11 14:55:59Wall time 14:56:00 - DB row time 2012-01-11 14:55:59Wall time 14:56:01 - DB row time 2012-01-11 14:55:59Wall time 14:56:02 - DB row time 2012-01-11 14:56:02Wall time 14:56:03 - DB row time 2012-01-11 14:56:02Wall time 14:56:04 - DB row time 2012-01-11 14:56:02Wall time 14:56:05 - DB row time 2012-01-11 14:56:05
Как может быть замечен по примеру, любому TTL основанный кэш может служить
устаревшим данным. Записи кэша автоматически не лишаются законной силы, если базовые данные изменяются.
Приложения используя значение по умолчанию TTL стратегия аннулирования должна
быть в состоянии работать правильно с устаревшими данными.
Определяемый пользователем обработчик хранения кэша может реализовать любую стратегию аннулирования работать вокруг этого ограничения.
Значение по умолчанию TTL может быть отвергнут, используя подсказку SQL /*qc_tt=seconds*/. Подсказка SQL должна быть, сразу появляются после подсказки
SQL, которая позволяет кэшироваться. Рекомендуется использовать константу PHP MYSQLND_QC_TTL_SWITCH вместо того, чтобы
использовать строковое значение.
Пример 22.313. Установка TTL с подсказками SQL
<?php$start = microtime(true);/* Connect, create and populate test table */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id INT)");$mysqli->query("INSERT INTO test(id) VALUES (1), (2)");printf("Default TTL\t: %d seconds\n", ini_get("mysqlnd_qc.ttl"));/* Will be cached for 2 seconds */$sql = sprintf("/*%s*//*%s%d*/SELECT id FROM test WHERE id = 1", MYSQLND_QC_ENABLE_SWITCH, MYSQLND_QC_TTL_SWITCH, 2);$res = $mysqli->query($sql);var_dump($res->fetch_assoc());$res->free();$mysqli->query("DELETE FROM test WHERE id = 1");sleep(1);/* Cache hit - no automatic invalidation and still valid! */$res = $mysqli->query($sql);var_dump($res->fetch_assoc());$res->free();sleep(2);/* Cache miss - cache entry has expired */$res = $mysqli->query($sql);var_dump($res->fetch_assoc());$res->free();printf("Script runtime\t: %d seconds\n", microtime(true) - $start);?>
Вышеупомянутые примеры выведут что-то подобное:
Default TTL : 30 secondsarray(1) { ["id"]=> string(1) "1"}array(1) { ["id"]=> string(1) "1"}NULLScript runtime : 3 seconds
Copyright 1997-2012 PHP Documentation Group.
У приложения есть три опции для того, чтобы сказать PECL/mysqlnd_qc, должен ли использоваться определенный
оператор. Наиболее основной подход должен кэшировать все операторы, устанавливая mysqlnd_qc.cache_by_default = 1. Этот подход
часто имеет небольшое практическое значение. Но это позволяет пользователям сделать быструю оценку об
усилениях максимальной производительности от кэширования. Приложение, разработанное, чтобы использовать кэш,
может быть в состоянии снабдить префиксом выбранные операторы соответствующие подсказки SQL. Однако,
изменение исходного кода приложений, возможно, всегда не возможно или не требуется, например, чтобы избежать
проблем с обновлениями программного обеспечения. Поэтому, PECL/mysqlnd_qc позволяет устанавливать обратный
вызов, который решает, должен ли запрос кэшироваться.
Обратный вызов устанавливается с mysqlnd_qc_set_is_select
функция. Обратному вызову дают строку оператора каждого оператора, осмотренного плагином. Затем, обратный
вызов может решить, кэшировать ли функцию. Обратный вызов, как предполагается, возвращается FALSE если оператор не должен кэшироваться. Возвращаемое значение TRUE делает сменную попытку добавить оператор в кэш. Записи кэша дадут TTL
значения по умолчанию (
mysqlnd_qc.ttl). Если обратный вызов возвращает численное значение, он используется в
качестве TTL вместо глобального значения по умолчанию.
Пример 22.314. Установка обратного вызова сmysqlnd_qc_set_is_select
mysqlnd_qc.enable_qc=1mysqlnd_qc.collect_statistics=1
<?php/* callback which decides if query is cached */function is_select($query) { static $patterns = array( /* true - use default from mysqlnd_qc.ttl */ "@SELECT\s+.*\s+FROM\s+test@ismU" => true, /* 3 - use TTL = 3 seconds */ "@SELECT\s+.*\s+FROM\s+news@ismU" => 3 ); /* check if query does match pattern */ foreach ($patterns as $pattern => $ttl) { if (preg_match($pattern, $query)) { printf("is_select(%45s): cache\n", $query); return $ttl; } } printf("is_select(%45s): do not cache\n", $query); return false;}/* install callback */mysqlnd_qc_set_is_select("is_select");/* Connect, create and populate test table */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id INT)");$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");/* cache put */$mysqli->query("SELECT id FROM test WHERE id = 1");/* cache hit */$mysqli->query("SELECT id FROM test WHERE id = 1");/* cache put */$mysqli->query("SELECT * FROM test");$stats = mysqlnd_qc_get_core_stats();printf("Cache put: %d\n", $stats['cache_put']);printf("Cache hit: %d\n", $stats['cache_hit']);?>
Вышеупомянутые примеры выведут что-то подобное:
is_select( DROP TABLE IF EXISTS test): do not cacheis_select( CREATE TABLE test(id INT)): do not cacheis_select( INSERT INTO test(id) VALUES (1), (2), (3)): do not cacheis_select( SELECT id FROM test WHERE id = 1): cacheis_select( SELECT id FROM test WHERE id = 1): cacheis_select( SELECT * FROM test): cacheCache put: 2Cache hit: 1
Обратный вызов в качестве примера тестирует, если строка оператора соответствует образец. Если это верно,
это любой возвраты TRUE кэшировать оператор, используя глобальный TTL значения
по умолчанию или альтернативный TTL.
Минимизировать приложение изменяется, обратный вызов может поместить в, и зарегистрированный в автоматическом предварительно ожидают файл.
Copyright 1997-2012 PHP Documentation Group.
Ужасно разработанный кэш может принести больше вреда, чем пользы. В худшем случае кэш может увеличить загрузку сервера базы данных вместо того, чтобы минимизировать это. Ситуация с перегрузкой может произойти, если чрезвычайно совместно используемая запись кэша истекает (бросающийся в паническое бегство кэш).
Записи кэша совместно используются и снова используются до различного градуса в зависимости от используемого хранения. Обработчик хранения значения по умолчанию хранит записи кэша в памяти процесса. Таким образом запись кэша может быть снова использована для продолжительности жизни процесса. Другие процессы PHP не могут получить доступ к этому. Если Memcache используется, запись кэша может быть совместно использована среди многократных процессов PHP и даже среди многократных машин, в зависимости от набора, используясь.
Если очень совместно используемая сохраненная запись кэша, например, в Memcache истекает, много клиентов получает неудачное обращение в кэш. Много клиентских запросов больше не могут быть поданы от кэша, но попытки выполнить базовый запрос на сервере базы данных. Пока запись кэша не обновляется, все больше клиентов связывается с сервером базы данных. В худшем случае общее количество, потерянное службы, является результатом.
Перегрузка может избегаться использования обработчик хранения, который ограничивает повторное использование записей кэша в немного клиентов. Затем, в среднем числе, ее вероятное, что только ограниченное количество клиентов попытается обновить запись кэша одновременно.
Дополнительно, встроенный защитный механизм хлопка может и должен использоваться. Если защита хлопка
активируется, записи кэша с истекшим сроком дают расширенное время жизни. Первый клиент, получающий
неудачное обращение в кэш для записи кэша с истекшим сроком, пытается обновить запись кэша в пределах
расширенного времени жизни. Все другие клиенты, запрашивающие запись кэша, временно обслуживаются от кэша
хотя оригинал TTL из кэша истекла запись. Другие клиенты не будут испытывать
неудачное обращение в кэш прежде, чем расширенное время жизни будет закончено.
Пример 22.315. Включение защитному механизму хлопка
mysqlnd_qc.slam_defense=1mysqlnd_qc.slam_defense_ttl=1
Защитный механизм хлопка включается с конфигурационной директивой PHP mysqlnd_qc.slam_defense. Расширенное время жизни записи кэша устанавливается
с mysqlnd_qc.slam_defense_ttl.
Функция mysqlnd_qc_get_core_stats возвращает подбор статистических данных.
Статистика slam_stale_refresh и slam_stale_hit
постепенно увеличиваются, если защита хлопка имеет место.
Не возможно дать рекомендацию, "каждый соответствует всем" на конфигурации защиты хлопка. Пользователям советуют контролировать и протестировать их установку и получить настройки соответственно.
Copyright 1997-2012 PHP Documentation Group.
Оператор нужно рассмотреть для того, чтобы кэшироваться, если он часто выполняется и имеет долгое время
выполнения. Кандидаты кэша находятся, создавая список операторов, сортированных продуктом числа выполнения,
умноженного на время выполнения операторов. Функция mysqlnd_qc_get_query_trace_log возвращает журнал запросов, которые
помогают с задачей.
Сбор трассировки запроса является медленной работой. Таким образом это отключается по умолчанию.
Конфигурационная директива PHP mysqlnd_qc.collect_query_trace используется, чтобы включить этому.
Трассировка функций содержит одну запись для каждого запроса, выпущенного прежде, чем функция будет вызвана.
Пример 22.316. Сбор трассировки запроса
mysqlnd_qc.enable_qc=1mysqlnd_qc.collect_query_trace=1
<?php/* connect to MySQL */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");/* dummy queries to fill the query trace */for ($i = 0; $i < 2; $i++) { $res = $mysqli->query("SELECT 1 AS _one FROM DUAL"); $res->free();}/* dump trace */var_dump(mysqlnd_qc_get_query_trace_log());?>
Вышеупомянутые примеры выведут:
array(2) { [0]=> array(8) { ["query"]=> string(26) "SELECT 1 AS _one FROM DUAL" ["origin"]=> string(102) "#0 qc.php(7): mysqli->query('SELECT 1 AS _on...')#1 {main}" ["run_time"]=> int(0) ["store_time"]=> int(25) ["eligible_for_caching"]=> bool(false) ["no_table"]=> bool(false) ["was_added"]=> bool(false) ["was_already_in_cache"]=> bool(false) } [1]=> array(8) { ["query"]=> string(26) "SELECT 1 AS _one FROM DUAL" ["origin"]=> string(102) "#0 qc.php(7): mysqli->query('SELECT 1 AS _on...')#1 {main}" ["run_time"]=> int(0) ["store_time"]=> int(8) ["eligible_for_caching"]=> bool(false) ["no_table"]=> bool(false) ["was_added"]=> bool(false) ["was_already_in_cache"]=> bool(false) }}
Различная информация дается в трассировке. Среди них синхронизации и источник вызова запроса. Свойство
источника содержит след кода, чтобы идентифицировать источник запроса. Глубина следа может быть ограничена с
конфигурационной директивой PHP mysqlnd_qc.query_trace_bt_depth. Глубина значения по умолчанию 3.
Пример 22.317. Установка глубины следа с mysqlnd_qc.query_trace_bt_depth
inisetting
mysqlnd_qc.enable_qc=1mysqlnd_qc.collect_query_trace=1
<?php/* connect to MySQL */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id INT)");$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");/* dummy queries to fill the query trace */for ($i = 0; $i < 3; $i++) { $res = $mysqli->query("SELECT id FROM test WHERE id = " . $mysqli->real_escape_string($i)); $res->free();}$trace = mysqlnd_qc_get_query_trace_log();$summary = array();foreach ($trace as $entry) { if (!isset($summary[$entry['query']])) { $summary[$entry['query']] = array( "executions" => 1, "time" => $entry['run_time'] + $entry['store_time'], ); } else { $summary[$entry['query']]['executions']++; $summary[$entry['query']]['time'] += $entry['run_time'] + $entry['store_time']; }}foreach ($summary as $query => $details) { printf("%45s: %5dms (%dx)\n", $query, $details['time'], $details['executions']);}?>
Вышеупомянутые примеры выведут что-то подобное:
DROP TABLE IF EXISTS test: 0ms (1x) CREATE TABLE test(id INT): 0ms (1x) INSERT INTO test(id) VALUES (1), (2), (3): 0ms (1x) SELECT id FROM test WHERE id = 0: 25ms (1x) SELECT id FROM test WHERE id = 1: 10ms (1x) SELECT id FROM test WHERE id = 2: 9ms (1x)
Copyright 1997-2012 PHP Documentation Group.
PECL/mysqlnd_qc предлагает три способа измерить эффективность кэша. Функция mysqlnd_qc_get_normalized_query_trace_log статистика возвратов,
агрегированная нормализованной строкой запроса, mysqlnd_qc_get_cache_info дает обработчику хранения определенную
информацию, которая включает список всех кэшируемых элементов, в зависимости от обработчика хранения.
Дополнительно, ядро PECL/mysqlnd_qc собирает высокоуровневые сводные статистические данные, агрегированные
на процесс PHP. Высокоуровневые статистические данные возвращаются mysqlnd_qc_get_core_stats.
Функции mysqlnd_qc_get_normalized_query_trace_log
и mysqlnd_qc_get_core_stats не будет собирать данные, если сбор данных не
был включен через их соответствующие конфигурационные директивы PHP. Сбор данных отключается по умолчанию
для соображений производительности. Это конфигурируемо с mysqlnd_qc.time_statistics
опцией, которая определяет, должна ли информация синхронизации быть собрана. Набор статистики времени
включается по умолчанию, но только выполняется, если сбор данных как таковой был включен. Запись статистики
времени вызывает дополнительные системные вызовы. В большинстве случаев преимущество контроля перевешивает
любую потенциальную потерю производительности дополнительных системных вызовов.
Пример 22.318. Сбор данных статистики сmysqlnd_qc.time_statistics установка ini
mysqlnd_qc.enable_qc=1mysqlnd_qc.collect_statistics=1
<?php/* connect to MySQL */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id INT)");$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");/* dummy queries */for ($i = 1; $i <= 4; $i++) { $query = sprintf("/*%s*/SELECT id FROM test WHERE id = %d", MYSQLND_QC_ENABLE_SWITCH, $i % 2); $res = $mysqli->query($query); $res->free();}var_dump(mysqlnd_qc_get_core_stats());?>
Вышеупомянутые примеры выведут что-то подобное:
array(26) { ["cache_hit"]=> string(1) "2" ["cache_miss"]=> string(1) "2" ["cache_put"]=> string(1) "2" ["query_should_cache"]=> string(1) "4" ["query_should_not_cache"]=> string(1) "3" ["query_not_cached"]=> string(1) "3" ["query_could_cache"]=> string(1) "4" ["query_found_in_cache"]=> string(1) "2" ["query_uncached_other"]=> string(1) "0" ["query_uncached_no_table"]=> string(1) "0" ["query_uncached_no_result"]=> string(1) "0" ["query_uncached_use_result"]=> string(1) "0" ["query_aggr_run_time_cache_hit"]=> string(2) "28" ["query_aggr_run_time_cache_put"]=> string(3) "900" ["query_aggr_run_time_total"]=> string(3) "928" ["query_aggr_store_time_cache_hit"]=> string(2) "14" ["query_aggr_store_time_cache_put"]=> string(2) "40" ["query_aggr_store_time_total"]=> string(2) "54" ["receive_bytes_recorded"]=> string(3) "136" ["receive_bytes_replayed"]=> string(3) "136" ["send_bytes_recorded"]=> string(2) "84" ["send_bytes_replayed"]=> string(2) "84" ["slam_stale_refresh"]=> string(1) "0" ["slam_stale_hit"]=> string(1) "0" ["request_counter"]=> int(1) ["process_hash"]=> int(1929695233)}
Для быстрого краткого обзора вызвать mysqlnd_qc_get_core_stats. Это поставляет использованию кэша, синхронизации
кэша и трафику связанную статистику. Значения агрегированы на основе для каждого процесса для всех запросов,
выпущенных любым вызовом API MySQL PHP.
Некоторый обработчик хранения, такой как обработчик значения по умолчанию, может сообщить о записях кэша,
статистика, связанная с записями и метаданными для базового запроса через mysqlnd_qc_get_cache_info функция. Пожалуйста, отметьте, что
возвращенная информация зависит от обработчика хранения. Значения агрегированы на основе для каждого
процесса.
Пример 22.319. Пример mysqlnd_qc_get_cache_infoиспользование
mysqlnd_qc.enable_qc=1
<?php/* connect to MySQL */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id INT)");$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");/* dummy queries to fill the query trace */for ($i = 1; $i <= 4; $i++) { $query = sprintf("/*%s*/SELECT id FROM test WHERE id = %d", MYSQLND_QC_ENABLE_SWITCH, $i % 2); $res = $mysqli->query($query); $res->free();}var_dump(mysqlnd_qc_get_cache_info());?>
Вышеупомянутые примеры выведут что-то подобное:
array(4) { ["num_entries"]=> int(2) ["handler"]=> string(7) "default" ["handler_version"]=> string(5) "1.0.0" ["data"]=> array(2) { ["Localhost via UNIX socket3306roottest|/*qc=on*/SELECT id FROM test WHERE id = 1"]=> array(2) { ["statistics"]=> array(11) { ["rows"]=> int(1) ["stored_size"]=> int(71) ["cache_hits"]=> int(1) ["run_time"]=> int(391) ["store_time"]=> int(27) ["min_run_time"]=> int(16) ["max_run_time"]=> int(16) ["min_store_time"]=> int(8) ["max_store_time"]=> int(8) ["avg_run_time"]=> int(8) ["avg_store_time"]=> int(4) } ["metadata"]=> array(1) { [0]=> array(8) { ["name"]=> string(2) "id" ["orig_name"]=> string(2) "id" ["table"]=> string(4) "test" ["orig_table"]=> string(4) "test" ["db"]=> string(4) "test" ["max_length"]=> int(1) ["length"]=> int(11) ["type"]=> int(3) } } } ["Localhost via UNIX socket3306roottest|/*qc=on*/SELECT id FROM test WHERE id = 0"]=> array(2) { ["statistics"]=> array(11) { ["rows"]=> int(0) ["stored_size"]=> int(65) ["cache_hits"]=> int(1) ["run_time"]=> int(299) ["store_time"]=> int(13) ["min_run_time"]=> int(11) ["max_run_time"]=> int(11) ["min_store_time"]=> int(6) ["max_store_time"]=> int(6) ["avg_run_time"]=> int(5) ["avg_store_time"]=> int(3) } ["metadata"]=> array(1) { [0]=> array(8) { ["name"]=> string(2) "id" ["orig_name"]=> string(2) "id" ["table"]=> string(4) "test" ["orig_table"]=> string(4) "test" ["db"]=> string(4) "test" ["max_length"]=> int(0) ["length"]=> int(11) ["type"]=> int(3) } } } }}
Возможно далее сломать гранулярность статистики к уровню нормализованной строки оператора. Нормализованная
строка оператора является строкой операторов со всеми параметрами, замененными вопросительными знаками.
Например, эти два оператора SELECT id FROM test WHERE id = 0 и SELECT id FROM test WHERE id = 1 нормализуются в SELECT
id FROM test WHERE id = ?. Их оба статистических данных агрегированы в одну запись для SELECT id FROM test WHERE id = ?.
Пример 22.320. Пример mysqlnd_qc_get_normalized_query_trace_logиспользование
mysqlnd_qc.enable_qc=1mysqlnd_qc.collect_normalized_query_trace=1
<?php/* connect to MySQL */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id INT)");$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");/* dummy queries to fill the query trace */for ($i = 1; $i <= 4; $i++) { $query = sprintf("/*%s*/SELECT id FROM test WHERE id = %d", MYSQLND_QC_ENABLE_SWITCH, $i % 2); $res = $mysqli->query($query); $res->free();}var_dump(mysqlnd_qc_get_normalized_query_trace_log());?>
Вышеупомянутые примеры выведут что-то подобное:
array(4) { [0]=> array(9) { ["query"]=> string(25) "DROP TABLE IF EXISTS test" ["occurences"]=> int(0) ["eligible_for_caching"]=> bool(false) ["avg_run_time"]=> int(0) ["min_run_time"]=> int(0) ["max_run_time"]=> int(0) ["avg_store_time"]=> int(0) ["min_store_time"]=> int(0) ["max_store_time"]=> int(0) } [1]=> array(9) { ["query"]=> string(27) "CREATE TABLE test (id INT )" ["occurences"]=> int(0) ["eligible_for_caching"]=> bool(false) ["avg_run_time"]=> int(0) ["min_run_time"]=> int(0) ["max_run_time"]=> int(0) ["avg_store_time"]=> int(0) ["min_store_time"]=> int(0) ["max_store_time"]=> int(0) } [2]=> array(9) { ["query"]=> string(46) "INSERT INTO test (id ) VALUES (? ), (? ), (? )" ["occurences"]=> int(0) ["eligible_for_caching"]=> bool(false) ["avg_run_time"]=> int(0) ["min_run_time"]=> int(0) ["max_run_time"]=> int(0) ["avg_store_time"]=> int(0) ["min_store_time"]=> int(0) ["max_store_time"]=> int(0) } [3]=> array(9) { ["query"]=> string(31) "SELECT id FROM test WHERE id =?" ["occurences"]=> int(4) ["eligible_for_caching"]=> bool(true) ["avg_run_time"]=> int(179) ["min_run_time"]=> int(11) ["max_run_time"]=> int(393) ["avg_store_time"]=> int(12) ["min_store_time"]=> int(7) ["max_store_time"]=> int(25) }}
Исходное распределение PECL/mysqlnd_qc содержит каталог web/ в котором могут
быть найдены веб-контрольные сценарии, которые дают пример, как записать монитор кэша. Пожалуйста, следуйте
инструкциям, данным в источнике.
Начиная с PECL/mysqlnd_qc 1.1.0 возможно записать статистику в файл журнала. Пожалуйста, см.
mysqlnd_qc.collect_statistics_log_file.
Copyright 1997-2012 PHP Documentation Group.
Плагин кэша запроса поддерживает использование определяемого пользователем обработчика хранения. Определяемый пользователем обработчик хранения может использовать произвольно сложные алгоритмы аннулирования и поддерживать произвольные носители.
Все определяемые пользователем обработчики хранения должны обеспечить определенный интерфейс. Функции определяемого пользователем обработчика хранения будут вызваны ядром плагина кэша. Необходимый интерфейс состоит из семи общедоступных функций. И процедурный и объектно-ориентированный определяемый пользователем обработчик хранения должен реализовать тот же самый набор функций.
Пример 22.321. Используя определяемый пользователем обработчик хранения
<?php/* Enable default caching of all statements */ini_set("mysqlnd_qc.cache_by_default", 1);/* Procedural user defined storage handler functions */$__cache = array();function get_hash($host_info, $port, $user, $db, $query) { global $__cache; printf("\t%s(%d)\n", __FUNCTION__, func_num_args()); return md5(sprintf("%s%s%s%s%s", $host_info, $port, $user, $db, $query));}function find_query_in_cache($key) { global $__cache; printf("\t%s(%d)\n", __FUNCTION__, func_num_args()); if (isset($__cache[$key])) { $tmp = $__cache[$key]; if ($tmp["valid_until"] < time()) { unset($__cache[$key]); $ret = NULL; } else { $ret = $__cache[$key]["data"]; } } else { $ret = NULL; } return $ret;}function return_to_cache($key) { /* Called on cache hit after cached data has been processed, may be used for reference counting */ printf("\t%s(%d)\n", __FUNCTION__, func_num_args());}function add_query_to_cache_if_not_exists($key, $data, $ttl, $run_time, $store_time, $row_count) { global $__cache; printf("\t%s(%d)\n", __FUNCTION__, func_num_args()); $__cache[$key] = array( "data" => $data, "row_count" => $row_count, "valid_until" => time() + $ttl, "hits" => 0, "run_time" => $run_time, "store_time" => $store_time, "cached_run_times" => array(), "cached_store_times" => array(), ); return TRUE;}function query_is_select($query) { printf("\t%s('%s'): ", __FUNCTION__, $query); $ret = FALSE; if (stristr($query, "SELECT") !== FALSE) { /* cache for 5 seconds */ $ret = 5; } printf("%s\n", (FALSE === $ret) ? "FALSE" : $ret); return $ret;}function update_query_run_time_stats($key, $run_time, $store_time) { global $__cache; printf("\t%s(%d)\n", __FUNCTION__, func_num_args()); if (isset($__cache[$key])) { $__cache[$key]['hits']++; $__cache[$key]["cached_run_times"][] = $run_time; $__cache[$key]["cached_store_times"][] = $store_time; }}function get_stats($key = NULL) { global $__cache; printf("\t%s(%d)\n", __FUNCTION__, func_num_args()); if ($key && isset($__cache[$key])) { $stats = $__cache[$key]; } else { $stats = array(); foreach ($__cache as $key => $details) { $stats[$key] = array( 'hits' => $details['hits'], 'bytes' => strlen($details['data']), 'uncached_run_time' => $details['run_time'], 'cached_run_time' => (count($details['cached_run_times'])) ? array_sum($details['cached_run_times']) / count($details['cached_run_times']) : 0, ); } } return $stats;}function clear_cache() { global $__cache; printf("\t%s(%d)\n", __FUNCTION__, func_num_args()); $__cache = array(); return TRUE;}/* Install procedural user-defined storage handler */if (!mysqlnd_qc_set_user_handlers("get_hash", "find_query_in_cache", "return_to_cache", "add_query_to_cache_if_not_exists", "query_is_select", "update_query_run_time_stats", "get_stats", "clear_cache")) { printf("Failed to install user-defined storage handler\n");}/* Connect, create and populate test table */$mysqli = new mysqli("host", "user", "password", "schema", "port", "socket");$mysqli->query("DROP TABLE IF EXISTS test");$mysqli->query("CREATE TABLE test(id INT)");$mysqli->query("INSERT INTO test(id) VALUES (1), (2)");printf("\nCache put/cache miss\n");$res = $mysqli->query("SELECT id FROM test WHERE id = 1");var_dump($res->fetch_assoc());$res->free();/* Delete record to verify we get our data from the cache */$mysqli->query("DELETE FROM test WHERE id = 1");printf("\nCache hit\n");$res = $mysqli->query("SELECT id FROM test WHERE id = 1");var_dump($res->fetch_assoc());$res->free();printf("\nDisplay cache statistics\n");var_dump(mysqlnd_qc_get_cache_info());printf("\nFlushing cache, cache put/cache miss");var_dump(mysqlnd_qc_clear_cache());$res = $mysqli->query("SELECT id FROM test WHERE id = 1");var_dump($res->fetch_assoc());$res->free();?>
Вышеупомянутые примеры выведут что-то подобное:
query_is_select('DROP TABLE IF EXISTS test'): FALSE query_is_select('CREATE TABLE test(id INT)'): FALSE query_is_select('INSERT INTO test(id) VALUES (1), (2)'): FALSECache put/cache miss query_is_select('SELECT id FROM test WHERE id = 1'): 5 get_hash(5) find_query_in_cache(1) add_query_to_cache_if_not_exists(6)array(1) { ["id"]=> string(1) "1"} query_is_select('DELETE FROM test WHERE id = 1'): FALSECache hit query_is_select('SELECT id FROM test WHERE id = 1'): 5 get_hash(5) find_query_in_cache(1) return_to_cache(1) update_query_run_time_stats(3)array(1) { ["id"]=> string(1) "1"}Display cache statistics get_stats(0)array(4) { ["num_entries"]=> int(1) ["handler"]=> string(4) "user" ["handler_version"]=> string(5) "1.0.0" ["data"]=> array(1) { ["18683c177dc89bb352b29965d112fdaa"]=> array(4) { ["hits"]=> int(1) ["bytes"]=> int(71) ["uncached_run_time"]=> int(398) ["cached_run_time"]=> int(4) } }}Flushing cache, cache put/cache miss clear_cache(0)bool(true) query_is_select('SELECT id FROM test WHERE id = 1'): 5 get_hash(5) find_query_in_cache(1) add_query_to_cache_if_not_exists(6)NULL