| 22.9.7. Mysqlnd query result cache plugin (mysqlnd_qc) Copyright 1997-2012 the PHP Documentation Group. The mysqlnd query result cache plugin adds easy to use client-side query caching to all PHP MySQL extensions using mysqlnd. As of version PHP 5.3.3 the MySQL native driver for PHP ( mysqlnd) features an internal plugin C API. C plugins, such as the query cache plugin, can extend the functionality of mysqlnd. Mysqlnd plugins such as the query cache plugin operate transparent from a user perspective. The cache plugin supports all PHP applications and all PHP MySQL extensions ( mysqli, mysql, PDO_MYSQL). It does not change existing APIs. No significant application changes are required to cache a query. The cache has two operation modes. It will either cache all queries (not recommended) or only those queries marked with a certain SQL hint (recommended). Copyright 1997-2012 the PHP Documentation Group. Transparent and therefore easy to use Flexible invalidation strategy Time-to-Live (TTL) user-defined
Storage with different scope and life-span Built-in slam defense to prevent cache stampeding.
Copyright 1997-2012 the PHP Documentation Group. The current 1.0.1 release of PECL mysqlnd_qc does not support PHP 5.4. Version 1.1.0-alpha lifts this limitation. Prepared statements and unbuffered queries are fully supported. Thus, the plugin is capable of caching all statements issued with mysqli or PDO_MySQL, which are the only two PHP MySQL APIs to offer prepared statement support. Copyright 1997-2012 the PHP Documentation Group. The shortcut mysqlnd_qc stands for mysqlnd query cache plugin. The name was chosen for a quick-and-dirty proof-of-concept. In the beginning the developers did not expect to continue using the code base. Sometimes PECL/mysqlnd_qc has also been called client-side query result set cache. 22.9.7.4. Quickstart and Examples Copyright 1997-2012 the PHP Documentation Group. The mysqlnd query cache plugin is easy to use. This quickstart will demo typical use-cases, and provide practical advice on getting started. It is strongly recommended to read the reference sections in addition to the quickstart. It is safe to begin with the quickstart. However, before using the plugin in mission critical environments we urge you to read additionally the background information from the reference sections. Most of the examples use the mysqli extension because it is the most feature complete PHP MySQL extension. However, the plugin can be used with any PHP MySQL extension that is using the mysqlnd library. 22.9.7.4.1. Architecture and Concepts Copyright 1997-2012 the PHP Documentation Group. The query cache plugin is implemented as a PHP extension. It is written in C and operates under the hood of PHP. During the startup of the PHP interpreter, it gets registered as a mysqlnd plugin to replace selected mysqlnd C methods. Hereby, it can change the behaviour of any PHP MySQL extension (mysqli, PDO_MYSQL, mysql) compiled to use the mysqlnd library without changing the extensions API. This makes the plugin compatible with each and every PHP MySQL application. Because existing APIs are not changed, it is almost transparent to use. Please, see the mysqlnd plugin API description for a discussion of the advantages of the plugin architecture and a comparison with proxy based solutions. Transparent to use At PHP run time PECL/mysqlnd_qc can proxy queries send from PHP (mysqlnd) to the MySQL server. It then inspects the statement string to find whether it shall cache its results. If so, result set is cached using a storage handler and further executions of the statement are served from the cache for a user-defined period. The Time to Live (TTL) of the cache entry can either be set globally or on a per statement basis. A statement is either cached if the plugin is instructed to cache all statements globally using a or, if the query string starts with the SQL hint (/*qc=on*/). The plugin is capable of caching any query issued by calling appropriate API calls of any of the existing PHP MySQL extensions. Flexible storage: various storage handler Various storage handler are supported to offer different scopes for cache entries. Different scopes allow for different degrees in sharing cache entries among clients. default (built-in): process memory, scope: process, one or more web requests depending on PHP deployment model used APC: shared memory, scope: single server, multiple web requests SQLite: memory or file, scope: single server, multiple web requests MEMCACHE: main memory, scope: single or multiple server, multiple web requests user (built-in): user-defined - any, scope: user-defined - any
Support for the APC, SQLite and MEMCACHE storage handler has to be enabled at compile time. The default and user handler are built-in. It is possible to switch between compiled-in storage handlers on a per query basis at run time. However, it is recommended to pick one storage handler and use it for all cache entries. Built-in slam defense to avoid overloading To avoid overload situations the cache plugin has a built-in slam defense mechanism. If a popular cache entries expires many clients using the cache entries will try to refresh the cache entry. For the duration of the refresh many clients may access the database server concurrently. In the worst case, the database server becomes overloaded and it takes more and more time to refresh the cache entry, which in turn lets more and more clients try to refresh the cache entry. To prevent this from happening the plugin has a slam defense mechanism. If slam defense is enabled and the plugin detects an expired cache entry it extends the life time of the cache entry before it refreshes the cache entry. This way other concurrent accesses to the expired cache entry are still served from the cache for a certain time. The other concurrent accesses to not trigger a concurrent refresh. Ideally, the cache entry gets refreshed by the client which extended the cache entries lifespan before other clients try to refresh the cache and potentially cause an overload situation. Unique approach to caching PECL/mysqlnd_qc has a unique approach to caching result sets that is superior to application based cache solutions. Application based solutions first fetch a result set into PHP variables. Then, the PHP variables are serialized for storage in a persistent cache, and then unserialized when fetching. The mysqlnd query cache stores the raw wire protocol data sent from MySQL to PHP in its cache and replays it, if still valid, on a cache hit. This way, it saves an extra serialization step for a cache put that all application based solutions have to do. It can store the raw wire protocol data in the cache without having to serialize into a PHP variable first and deserializing the PHP variable for storing in the cache again. Copyright 1997-2012 the PHP Documentation Group. The plugin is implemented as a PHP extension. See also the installation instructions to install the PECL/mysqlnd_qc extension. Compile or configure the PHP MySQL extension (mysqli, PDO_MYSQL, mysql) that you plan to use with support for the mysqlnd library. PECL/mysqlnd_qc is a plugin for the mysqlnd library. To use the plugin with any of the existing PHP MySQL extensions (APIs), the extension has to use the mysqlnd library. Then, load the extension into PHP and activate the plugin in the PHP configuration file using the PHP configuration directive named mysqlnd_qc.enable_qc. Example 22.291. Enabling the plugin (php.ini) 22.9.7.4.3. Caching queries Copyright 1997-2012 the PHP Documentation Group. There are four ways to trigger caching of a query. Use of SQL hints and mysqlnd_qc.cache_by_default = 1 are explained below. Please, refer to the function reference on mysqlnd_qc_is_select for a description of using a callback and, mysqlnd_qc_set_cache_condition on how to set rules for automatic caching. A SQL hint is a SQL standards compliant comment. As a SQL comment it is ignored by the database. A statement is considered eligible for caching if it either begins with the SQL hint enabling caching or it is a SELECT statement. An individual query which shall be cached must begin with the SQL hint /*qc=on*/. It is recommended to use the PHP constant MYSQLND_QC_ENABLE_SWITCH instead of using the string value. not eligible for caching and not cached: INSERT INTO test(id) VALUES (1) not eligible for caching and not cached: SHOW ENGINES eligible for caching but uncached: SELECT id FROM test eligible for caching and cached: /*qc=on*/SELECT id FROM test
The examples SELECT statement string is prefixed with the MYSQLND_QC_ENABLE_SWITCH SQL hint to enable caching of the statement. The SQL hint must be given at the very beginning of the statement string to enable caching. Example 22.292. Using the MYSQLND_QC_ENABLE_SWITCH SQL hint 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);?> The above examples will output something similar to: array(1) { ["id"]=> string(1) "1"}Total time uncached query: 0.000740sarray(1) { ["id"]=> string(1) "1"}Total time cached query: 0.000098s If nothing else is configured, as it is the case in the quickstart example, the plugin will use the built-in default storage handler. The default storage handler uses process memory to hold a cache entry. Depending on the PHP deployment model, a PHP process may serve one or more web requests. Please, consult the web server manual for details. Details make no difference for the examples given in the quickstart. The query cache plugin will cache all queries regardless if the query string begins with the SQL hint which enables caching or not, if the PHP configuration directive mysqlnd_qc.cache_by_default is set to 1. The setting mysqlnd_qc.cache_by_default is evaluated by the core of the query cache plugins. Neither the built-in nor user-defined storage handler can overrule the setting. The SQL hint /*qc=off*/ can be used to disable caching of individual queries if mysqlnd_qc.cache_by_default = 1 It is recommended to use the PHP constant MYSQLND_QC_DISABLE_SWITCH instead of using the string value. Example 22.293. Using the MYSQLND_QC_DISABLE_SWITCH SQL hint 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();?> The above examples will output: array(1) { ["id"]=> string(1) "1"}array(1) { ["id"]=> string(1) "1"}NULL PECL/mysqlnd_qc forbids caching of statements for which at least one column from the statements result set shows no table name in its meta data by default. This is usually the case for columns originating from SQL functions such as NOW() or LAST_INSERT_ID(). The policy aims to prevent pitfalls if caching by default is used. Example 22.294. Example showing which type of statements are not cached 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);}?> The above examples will output something similar to: 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 It is possible to enable caching for all statements including those which has columns in their result set for which MySQL reports no table, such as the statement from the example. Set mysqlnd_qc.cache_no_table = 1 to enable caching of such statements. Please, note the difference in the measured times for the above and below examples. Example 22.295. Enabling caching for all statements using themysqlnd_qc.cache_no_table ini setting 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);}?> The above examples will output something similar to: 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 22.9.7.4.4. Setting the TTL Copyright 1997-2012 the PHP Documentation Group. The default invalidation strategy of the query cache plugin is Time to Live (TTL). The built-in storage handlers will use the default TTL defined by the PHP configuration value mysqlnd_qc.ttl unless the query string contains a hint for setting a different TTL. The TTL is specified in seconds. By default cache entries expire after 30 seconds The example sets mysqlnd_qc.ttl=3 to cache statements for three seconds by default. Every second it updates a database table record to hold the current time and executes a SELECT statement to fetch the record from the database. The SELECT statement is cached for three seconds because it is prefixed with the SQL hint enabling caching. The output verifies that the query results are taken from the cache for the duration of three seconds before they are refreshed. Example 22.296. Setting the TTL with the mysqlnd_qc.ttl ini setting 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);}?> The above examples will output something similar to: 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 As can be seen from the example, any TTL based cache can serve stale data. Cache entries are not automatically invalidated, if underlying data changes. Applications using the default TTL invalidation strategy must be able to work correctly with stale data. A user-defined cache storage handler can implement any invalidation strategy to work around this limitation. The default TTL can be overruled using the SQL hint /*qc_tt=seconds*/. The SQL hint must be appear immediately after the SQL hint which enables caching. It is recommended to use the PHP constant MYSQLND_QC_TTL_SWITCH instead of using the string value. Example 22.297. Setting TTL with SQL hints <?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);?> The above examples will output something similar to: Default TTL : 30 secondsarray(1) { ["id"]=> string(1) "1"}array(1) { ["id"]=> string(1) "1"}NULLScript runtime : 3 seconds 22.9.7.4.5. Pattern based caching Copyright 1997-2012 the PHP Documentation Group. An application has three options for telling PECL/mysqlnd_qc whether a particular statement shall be used. The most basic approach is to cache all statements by setting mysqlnd_qc.cache_by_default = 1. This approach is often of little practical value. But it enables users to make a quick estimation about the maximum performance gains from caching. An application designed to use a cache may be able to prefix selected statements with the appropriate SQL hints. However, altering an applications source code may not always be possible or desired, for example, to avoid problems with software updates. Therefore, PECL/mysqlnd_qc allows setting a callback which decides if a query is to be cached. The callback is installed with the mysqlnd_qc_set_is_select function. The callback is given the statement string of every statement inspected by the plugin. Then, the callback can decide whether to cache the function. The callback is supposed to return FALSE if the statement shall not be cached. A return value of TRUE makes the plugin try to add the statement into the cache. The cache entry will be given the default TTL ( mysqlnd_qc.ttl). If the callback returns a numerical value it is used as the TTL instead of the global default. Example 22.298. Setting a callback withmysqlnd_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']);?> The above examples will output something similar to: 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 The examples callback tests if a statement string matches a pattern. If this is the case, it either returns TRUE to cache the statement using the global default TTL or an alternative TTL. To minimize application changes the callback can put into and registered in an auto prepend file. Copyright 1997-2012 the PHP Documentation Group. A badly designed cache can do more harm than good. In the worst case a cache can increase database server load instead of minimizing it. An overload situation can occur if a highly shared cache entry expires (cache stampeding). Cache entries are shared and reused to a different degree depending on the storage used. The default storage handler stores cache entries in process memory. Thus, a cache entry can be reused for the life-span of a process. Other PHP processes cannot access it. If Memcache is used, a cache entry can be shared among multiple PHP processes and even among multiple machines, depending on the set up being used. If a highly shared cache entry stored, for example, in Memcache expires, many clients gets a cache miss. Many client requests can no longer be served from the cache but try to run the underlying query on the database server. Until the cache entry is refreshed, more and more clients contact the database server. In the worst case, a total lost of service is the result. The overload can be avoided using a storage handler which limits the reuse of cache entries to few clients. Then, at the average, its likely that only a limited number of clients will try to refresh a cache entry concurrently. Additionally, the built-in slam defense mechanism can and should be used. If slam defense is activated an expired cache entry is given an extended life time. The first client getting a cache miss for the expired cache entry tries to refresh the cache entry within the extended life time. All other clients requesting the cache entry are temporarily served from the cache although the original TTL of the cache entry has expired. The other clients will not experience a cache miss before the extended life time is over. Example 22.299. Enabling the slam defense mechanism mysqlnd_qc.slam_defense=1mysqlnd_qc.slam_defense_ttl=1 The slam defense mechanism is enabled with the PHP configuration directive mysqlnd_qc.slam_defense. The extended life time of a cache entry is set with mysqlnd_qc.slam_defense_ttl. The function mysqlnd_qc_get_core_stats returns an array of statistics. The statistics slam_stale_refresh and slam_stale_hit are incremented if slam defense takes place. It is not possible to give a one-fits-all recommendation on the slam defense configuration. Users are advised to monitor and test their setup and derive settings accordingly. 22.9.7.4.7. Finding cache candidates Copyright 1997-2012 the PHP Documentation Group. A statement should be considered for caching if it is executed often and has a long run time. Cache candidates are found by creating a list of statements sorted by the product of the number of executions multiplied by the statements run time. The function mysqlnd_qc_get_query_trace_log returns a query log which help with the task. Collecting a query trace is a slow operation. Thus, it is disabled by default. The PHP configuration directive mysqlnd_qc.collect_query_trace is used to enable it. The functions trace contains one entry for every query issued before the function is called. Example 22.300. Collecting a query trace 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());?> The above examples will output: 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) }} Assorted information is given in the trace. Among them timings and the origin of the query call. The origin property holds a code backtrace to identify the source of the query. The depth of the backtrace can be limited with the PHP configuration directive mysqlnd_qc.query_trace_bt_depth. The default depth is 3. Example 22.301. Setting the backtrace depth with the 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']);}?> The above examples will output something similar to: 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) 22.9.7.4.8. Measuring cache efficiency Copyright 1997-2012 the PHP Documentation Group. PECL/mysqlnd_qc offers three ways to measure the cache efficiency. The function mysqlnd_qc_get_normalized_query_trace_log returns statistics aggregated by the normalized query string, mysqlnd_qc_get_cache_info gives storage handler specific information which includes a list of all cached items, depending on the storage handler. Additionally, the core of PECL/mysqlnd_qc collects high-level summary statistics aggregated per PHP process. The high-level statistics are returned by mysqlnd_qc_get_core_stats. The functions mysqlnd_qc_get_normalized_query_trace_log and mysqlnd_qc_get_core_stats will not collect data unless data collection has been enabled through their corresponding PHP configuration directives. Data collection is disabled by default for performance considerations. It is configurable with the mysqlnd_qc.time_statistics option, which determines if timing information should be collected. Collection of time statistics is enabled by default but only performed if data collection as such has been enabled. Recording time statistics causes extra system calls. In most cases, the benefit of the monitoring outweighs any potential performance penalty of the additional system calls. Example 22.302. Collecting statistics data with themysqlnd_qc.time_statistics ini setting 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());?> The above examples will output something similar to: 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)} For a quick overview, call mysqlnd_qc_get_core_stats. It delivers cache usage, cache timing and traffic related statistics. Values are aggregated on a per process basis for all queries issued by any PHP MySQL API call. Some storage handler, such as the default handler, can report cache entries, statistics related to the entries and meta data for the underlying query through the mysqlnd_qc_get_cache_info function. Please note, that the information returned depends on the storage handler. Values are aggregated on a per process basis. Example 22.303. Example mysqlnd_qc_get_cache_infousage 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());?> The above examples will output something similar to: 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) } } } }} It is possible to further break down the granularity of statistics to the level of the normalized statement string. The normalized statement string is the statements string with all parameters replaced with question marks. For example, the two statements SELECT id FROM test WHERE id = 0 and SELECT id FROM test WHERE id = 1 are normalized into SELECT id FROM test WHERE id = ?. Their both statistics are aggregated into one entry for SELECT id FROM test WHERE id = ?. Example 22.304. Example mysqlnd_qc_get_normalized_query_trace_logusage 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());?> The above examples will output something similar to: 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) }} The source distribution of PECL/mysqlnd_qc contains a directory web/ in which web based monitoring scripts can be found which give an example how to write a cache monitor. Please, follow the instructions given in the source. Since PECL/mysqlnd_qc 1.1.0 it is possible to write statistics into a log file. Please, see mysqlnd_qc.collect_statistics_log_file. 22.9.7.4.9. Beyond TTL: user-defined storage Copyright 1997-2012 the PHP Documentation Group. The query cache plugin supports the use of user-defined storage handler. User-defined storage handler can use arbitrarily complex invalidation algorithms and support arbitrary storage media. All user-defined storage handlers have to provide a certain interface. The functions of the user-defined storage handler will be called by the core of the cache plugin. The necessary interface consists of seven public functions. Both procedural and object oriented user-defined storage handler must implement the same set of functions. Example 22.305. Using a user-defined storage handler <?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();?> The above examples will output something similar to: 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 22.9.7.5. Installing/Configuring Copyright 1997-2012 the PHP Documentation Group. Copyright 1997-2012 the PHP Documentation Group. PHP 5.3.3 or a newer version of PHP 5.3. PHP 5.4.0 is not yet supported. PECL/mysqlnd_qc is a mysqlnd plugin. It plugs into the mysqlnd library. To use you plugin with a PHP MySQL extension (mysqli, mysql, PDO_MYSQL) it is necessary to enable use of the mysqlnd library by the PHP MySQL extension in question. Please refer to the extensions manual sections for details. For using APC storage handler: APC 3.1.3p1-beta or newer. For using MEMCACHE storage handler: libmemcache 0.38 or newer. For using sqlite storage handler: sqlite3 bundled with PHP. 22.9.7.5.3. Runtime Configuration Copyright 1997-2012 the PHP Documentation Group. The behaviour of these functions is affected by settings in php.ini. Table 22.73. mysqlnd_qc Configure Options Here's a short explanation of the configuration directives. - mysqlnd_qc.enable_qc integer
Enables or disables the plugin. If disabled the extension will not plug into mysqlnd to proxy internal mysqlnd C API calls. - mysqlnd_qc.ttl integer
Default Time-to-Live (TTL) for cache entries in seconds. - mysqlnd_qc.cache_by_default integer
Cache all queries regardless if they begin with the SQL hint that enables caching of a query or not. Storage handler cannot overrule the setting. It is evaluated by the core of the plugin. - mysqlnd_qc.cache_no_table integer
Whether to cache queries with no table name in any of columns meta data of their result set, for example, SELECT SLEEP(1), SELECT NOW(), SELECT SUBSTRING(). - mysqlnd_qc.use_request_time integer
Use PHP global request time to avoid gettimeofday() system calls? If using APC storage handler it should be set to the value of apc.use_request_time , if not warnings will be generated. - mysqlnd_qc.time_statistics integer
Collect run time and store time statistics using gettimeofday() system call? Data will be collected only if you also set mysqlnd_qc.collect_statistics = 1, - mysqlnd_qc.collect_statistics integer
Collect statistics for mysqlnd_qc_get_core_stats? Does not influence storage handler statistics! Handler statistics can be an integral part of the handler internal storage format. Thereofore, collection of some handler statistics cannot be disabled. - mysqlnd_qc.collect_statistics-log-file integer
If mysqlnd_qc.collect_statistics and mysqlnd_qc.collect_statistics_log_file are set, the plugin will dump statistics into the specified log file at every 10th web request during PHP request shutdown. The log file needs to be writable by the web server user. Since 1.1.0. - mysqlnd_qc.collect_query_trace integer
Collect query back traces? - mysqlnd_qc.query_trace_bt_depth integer
Maximum depth/level of a query code backtrace. - mysqlnd_qc.ignore_sql_comments integer
Whether to remove SQL comments from a query string before hashing it to generate a cache key. Disable if you do not want two statemts such as SELECT /*my_source_ip=123*/ id FROM test and SELECT /*my_source_ip=456*/ id FROM test to refer to the same cache entry. Since 1.1.0. - mysqlnd_qc.slam_defense integer
Activates handler based slam defense (cache stampeding protection) if available. Supported by Default and APC storage handler - mysqlnd_qc.slam_defense_ttl integer
TTL for stale cache entries which are served while another client updates the entries. Supported by APC storage handler. - mysqlnd_qc.collect_normalized_query_trace integer
Collect aggregated normalized query traces? The setting has no effect by default. You compile the extension using the define NORM_QUERY_TRACE_LOG to make use of the setting. - mysqlnd_qc.std_data_copy integer
Default storage handler: copy cached wire data? EXPERIMENTAL � use default setting! - mysqlnd_qc.apc_prefix string
The APC storage handler stores data in the APC user cache. The setting sets a prefix to be used for cache entries. - mysqlnd_qc.memc_server string
MEMCACHE storage handler: memcache server host. - mysqlnd_qc.memc_port integer
MEMCACHE storage handler: memcached server port. - mysqlnd_qc.sqlite_data_file string
sqlite storage handler: data file. Any setting but :memory: may be of little practical value.
22.9.7.6. Predefined Constants Copyright 1997-2012 the PHP Documentation Group. The constants below are defined by this extension, andwill only be available when the extension has eitherbeen compiled into PHP or dynamically loaded at runtime. SQL hint related Example 22.306. Using SQL hint constants The query cache is controlled by SQL hints. SQL hints are used to enable and disable caching. SQL hints can be used to set the TTL of a query. The SQL hints recognized by the query cache can be manually changed at compile time. This makes it possible to use mysqlnd_qc in environments in which the default SQL hints are already taken and interpreted by other systems. Therefore it is recommended to use the SQL hint string constants instead of manually adding the default SQL hints to the query string. <?php/* Use constants for maximum portability */$query = "/*" . MYSQLND_QC_ENABLE_SWITCH . "*/SELECT id FROM test";/* Valid but less portable: default TTL */$query = "/*qc=on*/SELECT id FROM test";/* Valid but less portable: per statement TTL */$query = "/*qc=on*//*qc_ttl=5*/SELECT id FROM test";printf("MYSQLND_QC_ENABLE_SWITCH: %s\n", MYSQLND_QC_ENABLE_SWITCH);printf("MYSQLND_QC_DISABLE_SWITCH: %s\n", MYSQLND_QC_DISABLE_SWITCH);printf("MYSQLND_QC_TTL_SWITCH: %s\n", MYSQLND_QC_TTL_SWITCH);?> The above examples will output: MYSQLND_QC_ENABLE_SWITCH: qc=onMYSQLND_QC_DISABLE_SWITCH: qc=offMYSQLND_QC_TTL_SWITCH: qc_ttl= - MYSQLND_QC_ENABLE_SWITCH (string)
- SQL hint used to enable caching of a query.
- MYSQLND_QC_DISABLE_SWITCH (string)
- SQL hint used to disable caching of a query if mysqlnd_qc.cache_by_default = 1.
- MYSQLND_QC_TTL_SWITCH (string)
- SQL hint used to set the TTL of a result set.
- MYSQLND_QC_SERVER_ID_SWITCH (string)
This SQL hint should not be used in general. It is needed by PECL/mysqlnd_ms to group cache entries for one statement but originating from different physical connections. If the hint is used connection settings such as user, hostname and charset are not considered for generating a cache key of a query. Instead the given value and the query string are used as input to the hashing function that generates the key. PECL/mysqlnd_ms may, if instructed, cache results from MySQL Replication slaves. Because it can hold many connections to the slave the cache key shall not be formed from the user, hostname or other settings that may vary for the various slave connections. Instead, PECL/mysqlnd_ms provides an identifier which refers to the group of slave connections that shall be enabled to share cache entries no matter which physical slave connection was to generate the cache entry. Use of this feature outside of PECL/mysqlnd_ms is not recommended.
mysqlnd_qc_set_cache_condition related Example 22.307. Example mysqlnd_qc_set_cache_conditionusage The function mysqlnd_qc_set_cache_condition allows setting conditions for automatic caching of statements which don't begin with the SQL hints necessary to manually enable caching. <?php/* Cache all accesses to tables with the name "new%" in schema/database "db_example" for 1 second */if (!mysqlnd_qc_set_cache_condition(MYSQLND_QC_CONDITION_META_SCHEMA_PATTERN, "db_example.new%", 1)) { die("Failed to set cache condition!");}$mysqli = new mysqli("host", "user", "password", "db_example", "port");/* cached although no SQL hint given */$mysqli->query("SELECT id, title FROM news");$pdo_mysql = new PDO("mysql:host=host;dbname=db_example;port=port", "user", "password");/* not cached: no SQL hint, no pattern match */$pdo_mysql->query("SELECT id, title FROM latest_news");/* cached: TTL 1 second, pattern match */$pdo_mysql->query("SELECT id, title FROM news");?> - MYSQLND_QC_CONDITION_META_SCHEMA_PATTERN (int)
- Used as a parameter of mysqlnd_qc_set_cache_condition to set conditions for schema based automatic caching.
22.9.7.7. mysqlnd_qc Functions Copyright 1997-2012 the PHP Documentation Group. 22.9.7.7.1. mysqlnd_qc_clear_cache Copyright 1997-2012 the PHP Documentation Group. mysqlnd_qc_clear_cache Flush all cache contents
Description bool mysqlnd_qc_clear_cache(); Flush all cache contents. Flushing the cache is a storage handler responsibility. All built-in storage handler but the memcache storage handler support flushing the cache. The memcache storage handler cannot flush its cache contents. User-defined storage handler may or may not support the operation. Parameters This function has no parameters. Return Values Returns TRUE on success or FALSE on failure. A return value of FALSE indicates that flushing all cache contents has failed or the operation is not supported by the active storage handler. Applications must not expect that calling the function will always flush the cache. 22.9.7.7.2. mysqlnd_qc_get_available_handlers Copyright 1997-2012 the PHP Documentation Group. Description array mysqlnd_qc_get_available_handlers(); Which storage are available depends on the compile time configuration of the query cache plugin. The default storage handler is always available. All other storage handler must be enabled explicitly when building the extension. Parameters This function has no parameters. Return Values Returns an array of available built-in storage handler. For each storage handler the version number and version string is given. Examples Example 22.308. mysqlnd_qc_get_available_handlersexample <?phpvar_dump(mysqlnd_qc_get_available_handlers());?> The above examples will output: array(5) { ["default"]=> array(2) { ["version"]=> string(5) "1.0.0" ["version_number"]=> int(100000) } ["user"]=> array(2) { ["version"]=> string(5) "1.0.0" ["version_number"]=> int(100000) } ["APC"]=> array(2) { ["version"]=> string(5) "1.0.0" ["version_number"]=> int(100000) } ["MEMCACHE"]=> array(2) { ["version"]=> string(5) "1.0.0" ["version_number"]=> int(100000) } ["sqlite"]=> array(2) { ["version"]=> string(5) "1.0.0" ["version_number"]=> int(100000) }} See Also 22.9.7.7.3. mysqlnd_qc_get_cache_info Copyright 1997-2012 the PHP Documentation Group. mysqlnd_qc_get_cache_info Returns information on the current handler, the number of cache entries and cache entries, if available
Description array mysqlnd_qc_get_cache_info(); Parameters This function has no parameters. Return Values Returns information on the current handler, the number of cache entries and cache entries, if available. If and what data will be returned for the cache entries is subject to the active storage handler. Storage handler are free to return any data. Storage handler are recommended to return at least the data provided by the default handler, if technically possible. The scope of the information is the PHP process. Dependng on the PHP deployment model a process may serve one or more web requests. Values are aggregated for all cache activities on a per storage handler basis. It is not possible to tell how much queries originating from mysqli, PDO_MySQL or mysql.API calls have contributed to the aggregated data values. Use mysqlnd_qc_get_core_stats to get timing data aggregated for all storage handlers. Array of cache information - handler string
The active storage handler. All storage handler. Since 1.0.0. - handler_version string
The version of the active storage handler. All storage handler. Since 1.0.0. - num_entries int
The number of cache entries. The value depends on the storage handler in use. The default, APC and SQLite storage handler provide the actual number of cache entries. The MEMCACHE storage handler always returns 0. MEMCACHE does not support counting the number of cache entries. If a user defined handler is used, the number of entries of the data property is reported. Since 1.0.0. - data array
The version of the active storage handler. Additional storage handler dependent data on the cache entries. Storage handler are requested to provide similar and comparable information. A user defined storage handler is free to return any data. Since 1.0.0. The following information is provided by the default storage handler for the data property. The data property holds a hash. The hash is indexed by the internal cache entry identifier of the storage handler. The cache entry identifier is human-readable and contains the query string leading to the cache entry. Please, see also the example below. The following data is given for every cache entry. - statistics array
Statistics of the cache entry. Since 1.0.0. - metadata array
Metadata of the cache entry. This is the metadata provided by MySQL together with the result set of the statement in question. Different versions of the MySQL server may return different metadata. Unlike with some of the PHP MySQL extensions no attempt is made to hide MySQL server version dependencies and version details from the caller. Please, refer to the MySQL C API documentation that belongs to the MySQL server in use for further details. The metadata list contains one entry for every column. Since 1.0.0.
The APC storage handler returns the same information for the data property but no metadata. The metadata of a cache entry is set to NULL. The MEMCACHE storage handler does not fill the data property. Statistics are not available on a per cache entry basis with the MEMCACHE storage handler. A user defined storage handler is free to provide any data.
Examples Example 22.309. mysqlnd_qc_get_cache_infoexample The example shows the output from the built-in default storage handler. Other storage handler may report different data. <?php/* Populate the cache, e.g. using mysqli */$mysqli = new mysqli("host", "user", "password", "schema");$mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/SELECT id FROM test");/* Display cache information */var_dump(mysqlnd_qc_get_cache_info());?> The above examples will output: array(4) { ["num_entries"]=> int(1) ["handler"]=> string(7) "default" ["handler_version"]=> string(5) "1.0.0" ["data"]=> array(1) { ["Localhost via UNIX socket 3306 user schema|/*qc=on*/SELECT id FROM test"]=> array(2) { ["statistics"]=> array(11) { ["rows"]=> int(6) ["stored_size"]=> int(101) ["cache_hits"]=> int(0) ["run_time"]=> int(471) ["store_time"]=> int(27) ["min_run_time"]=> int(0) ["max_run_time"]=> int(0) ["min_store_time"]=> int(0) ["max_store_time"]=> int(0) ["avg_run_time"]=> int(0) ["avg_store_time"]=> int(0) } ["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) "schema" ["max_length"]=> int(1) ["length"]=> int(11) ["type"]=> int(3) } } } }} See Also 22.9.7.7.4. mysqlnd_qc_get_core_stats Copyright 1997-2012 the PHP Documentation Group. Description array mysqlnd_qc_get_core_stats(); Returns an array of statistics collected by the core of the cache plugin. The same data fields will be reported for any storage handler because the data is collected by the core. The PHP configuration setting mysqlnd_qc.collect_statistics controls the collection of statistics. The collection of statistics is disabled by default for performance reasons. Disabling the collection of statistics will also disable the collection of time related statistics. The PHP configuration setting mysqlnd_qc.collect_time_statistics controls the collection of time related statistics. The scope of the core statistics is the PHP process. Depending on your deployment model a PHP process may handle one or multiple requests. Statistics are aggregated for all cache entries and all storage handler. It is not possible to tell how much queries originating from mysqli, PDO_MySQL or mysql API calls have contributed to the aggregated data values. Parameters This function has no parameters. Return Values Array of core statistics Examples Example 22.310. mysqlnd_qc_get_core_statsexample <?php/* Enable collection of statistics - default: disabled */ini_set("mysqlnd_qc.collect_statistics", 1);/* Enable collection of all timing related statistics -default: enabled but overruled by mysqlnd_qc.collect_statistics = 0 */ini_set("mysqlnd_qc.collect_time_statistics", 1);/* Populate the cache, e.g. using mysqli */$mysqli = new mysqli('host', 'user', 'password', 'schema');/* Cache miss and cache put */$mysqli->query("/*qc=on*/SELECT id FROM test");/* Cache hit */$mysqli->query("/*qc=on*/SELECT id FROM test");/* Display core statistics */var_dump(mysqlnd_qc_get_core_stats());?> The above examples will output: array(26) { ["cache_hit"]=> string(1) "1" ["cache_miss"]=> string(1) "1" ["cache_put"]=> string(1) "1" ["query_should_cache"]=> string(1) "2" ["query_should_not_cache"]=> string(1) "0" ["query_not_cached"]=> string(1) "0" ["query_could_cache"]=> string(1) "2" ["query_found_in_cache"]=> string(1) "1" ["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(1) "4" ["query_aggr_run_time_cache_put"]=> string(3) "395" ["query_aggr_run_time_total"]=> string(3) "399" ["query_aggr_store_time_cache_hit"]=> string(1) "2" ["query_aggr_store_time_cache_put"]=> string(1) "8" ["query_aggr_store_time_total"]=> string(2) "10" ["receive_bytes_recorded"]=> string(2) "65" ["receive_bytes_replayed"]=> string(2) "65" ["send_bytes_recorded"]=> string(2) "29" ["send_bytes_replayed"]=> string(2) "29" ["slam_stale_refresh"]=> string(1) "0" ["slam_stale_hit"]=> string(1) "0" ["request_counter"]=> int(1) ["process_hash"]=> int(3547549858)} See Also 22.9.7.7.5. mysqlnd_qc_get_normalized_query_trace_log Copyright 1997-2012 the PHP Documentation Group. Description array mysqlnd_qc_get_normalized_query_trace_log(); Returns a normalized query trace log for each query inspected by the query cache. The collection of the trace log is disabled by default. To collect the trace log you have to set the PHP configuration directive mysqlnd_qc.collect_normalized_query_trace to 1 Entries in the trace log are grouped by the normalized query statement. The normalized query statement is the query statement with all statement parameter values being replaced with a question mark. For example, the two statements SELECT id FROM test WHERE id = 1 and SELECT id FROM test WHERE id = 2 are normalized as SELECT id FROM test WHERE id = ?. Whenever a statement is inspected by the query cache which matches the normalized statement pattern, its statistics are grouped by the normalized statement string. Parameters This function has no parameters. Return Values An array of query log. Every list entry contains the normalized query stringand further detail information. Examples Example 22.311. mysqlnd_qc_get_normalized_query_trace_logexample mysqlnd_qc.collect_normalized_query_trace=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)");/* not cached */$res = $mysqli->query("SELECT id FROM test WHERE id = 1");var_dump($res->fetch_assoc());$res->free();/* cache put */$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 2");var_dump($res->fetch_assoc());$res->free();/* cache hit */$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 2");var_dump($res->fetch_assoc());$res->free();var_dump(mysqlnd_qc_get_normalized_query_trace_log());?> The above examples will output: array(1) { ["id"]=> string(1) "1"}array(1) { ["id"]=> string(1) "2"}array(1) { ["id"]=> string(1) "2"}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(40) "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(2) ["eligible_for_caching"]=> bool(true) ["avg_run_time"]=> int(159) ["min_run_time"]=> int(12) ["max_run_time"]=> int(307) ["avg_store_time"]=> int(10) ["min_store_time"]=> int(8) ["max_store_time"]=> int(13) }} See Also 22.9.7.7.6. mysqlnd_qc_get_query_trace_log Copyright 1997-2012 the PHP Documentation Group. Description array mysqlnd_qc_get_query_trace_log(); Returns a backtrace for each query inspected by the query cache. The collection of the backtrace is disabled by default. To collect the backtrace you have to set the PHP configuration directive mysqlnd_qc.collect_query_trace to 1 The maximum depth of the backtrace is limited to the depth set with the PHP configuration directive mysqlnd_qc.query_trace_bt_depth. Parameters This function has no parameters. Return Values An array of query backtrace. Every list entry contains the query string, a backtrace and further detail information. Examples Example 22.312. mysqlnd_qc_get_query_trace_logexample mysqlnd_qc.collect_query_trace=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)");/* not cached */$res = $mysqli->query("SELECT id FROM test WHERE id = 1");var_dump($res->fetch_assoc());$res->free();/* cache put */$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 2");var_dump($res->fetch_assoc());$res->free();/* cache hit */$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT id FROM test WHERE id = 2");var_dump($res->fetch_assoc());$res->free();var_dump(mysqlnd_qc_get_query_trace_log());?> The above examples will output: array(1) { ["id"]=> string(1) "1"}array(1) { ["id"]=> string(1) "2"}array(1) { ["id"]=> string(1) "2"}array(6) { [0]=> array(8) { ["query"]=> string(25) "DROP TABLE IF EXISTS test" ["origin"]=> string(102) "#0 qc.php(4): mysqli->query('DROP TABLE IF E...')#1 {main}" ["run_time"]=> int(0) ["store_time"]=> int(0) ["eligible_for_caching"]=> bool(false) ["no_table"]=> bool(false) ["was_added"]=> bool(false) ["was_already_in_cache"]=> bool(false) } [1]=> array(8) { ["query"]=> string(25) "CREATE TABLE test(id INT)" ["origin"]=> string(102) "#0 qc.php(5): mysqli->query('CREATE TABLE te...')#1 {main}" ["run_time"]=> int(0) ["store_time"]=> int(0) ["eligible_for_caching"]=> bool(false) ["no_table"]=> bool(false) ["was_added"]=> bool(false) ["was_already_in_cache"]=> bool(false) } [2]=> array(8) { ["query"]=> string(36) "INSERT INTO test(id) VALUES (1), (2)" ["origin"]=> string(102) "#0 qc.php(6): mysqli->query('INSERT INTO tes...')#1 {main}" ["run_time"]=> int(0) ["store_time"]=> int(0) ["eligible_for_caching"]=> bool(false) ["no_table"]=> bool(false) ["was_added"]=> bool(false) ["was_already_in_cache"]=> bool(false) } [3]=> array(8) { ["query"]=> string(32) "SELECT id FROM test WHERE id = 1" ["origin"]=> string(102) "#0 qc.php(9): mysqli->query('SELECT id FROM ...')#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) } [4]=> array(8) { ["query"]=> string(41) "/*qc=on*/SELECT id FROM test WHERE id = 2" ["origin"]=> string(103) "#0 qc.php(14): mysqli->query('/*qc=on*/SELECT...')#1 {main}" ["run_time"]=> int(311) ["store_time"]=> int(13) ["eligible_for_caching"]=> bool(true) ["no_table"]=> bool(false) ["was_added"]=> bool(true) ["was_already_in_cache"]=> bool(false) } [5]=> array(8) { ["query"]=> string(41) "/*qc=on*/SELECT id FROM test WHERE id = 2" ["origin"]=> string(103) "#0 qc.php(19): mysqli->query('/*qc=on*/SELECT...')#1 {main}" ["run_time"]=> int(13) ["store_time"]=> int(8) ["eligible_for_caching"]=> bool(true) ["no_table"]=> bool(false) ["was_added"]=> bool(false) ["was_already_in_cache"]=> bool(true) }} See Also 22.9.7.7.7. mysqlnd_qc_set_cache_condition Copyright 1997-2012 the PHP Documentation Group. Description bool mysqlnd_qc_set_cache_condition( int condition_type, mixed condition, mixed condition_option); Sets a condition for automatic caching of statements which do not contain the necessary SQL hints to enable caching of them. Parameters - condition_type
Type of the condition. The only allowed value is MYSQLND_QC_CONDITION_META_SCHEMA_PATTERN . - condition
Parameter for the condition set with condition_type. Parameter type and structure depend on condition_type If condition_type equals MYSQLND_QC_CONDITION_META_SCHEMA_PATTERN condition must be a string. The string sets a pattern. Statements are cached if table and database meta data entry of their result sets match the pattern. The pattern is checked for a match with the db and org_table meta data entries provided by the underlying MySQL client server library. Please, check the MySQL Reference manual for details about the two entries. The db and org_table values are concatenated with a dot (.) before matched against condition. Pattern matching supports the wildcards % and _. The wildcard % will match one or many arbitrary characters. _ will match one arbitrary character. The escape symbol is backslash. - condition_option
Option for condition. Type and structure depend on condition_type. If condition_type equals MYSQLND_QC_CONDITION_META_SCHEMA_PATTERN condition_options is the TTL to be used.
Examples Example 22.313. mysqlnd_qc_set_cache_conditionexample <?php/* Cache all accesses to tables with the name "new%" in schema/database "db_example"for 1 second */if (!mysqlnd_qc_set_cache_condition(MYSQLND_QC_CONDITION_META_SCHEMA_PATTERN,"db_example.new%", 1)) { die("Failed to set cache condition!");}$mysqli = new mysqli("host", "user", "password", "db_example", "port");/* cached although no SQL hint given */$mysqli->query("SELECT id, title FROM news");$pdo_mysql = new PDO("mysql:host=host;dbname=db_example;port=port", "user", "password");/* not cached: no SQL hint, no pattern match */$pdo_mysql->query("SELECT id, title FROM latest_news");/* cached: TTL 1 second, pattern match */$pdo_mysql->query("SELECT id, title FROM news");?> Return Values Returns TRUE on success or FALSE on FAILURE. See Also 22.9.7.7.8. mysqlnd_qc_set_is_select Copyright 1997-2012 the PHP Documentation Group. Description mixed mysqlnd_qc_set_is_select( string callback); Installs a callback which decides whether a statement is cached. There are several ways of hinting PELC/mysqlnd_qc to cache a query. By default, PECL/mysqlnd_qc attempts to cache a if caching of all statements is enabled or the query string begins with a certain SQL hint. The plugin internally calls a function named is_select() to find out. This internal function can be replaced with a user-defined callback. Then, the user-defined callback is responsible to decide whether the plugin attempts to cache a statement. Because the internal function is replaced with the callback, the callback gains full control. The callback is free to ignore the configuration setting mysqlnd_qc.cache_by_default and SQL hints. The callback is invoked for every statement inspected by the plugin. It is given the statements string as a parameter. The callback returns FALSE if the statement shall not be cached. It returns TRUE to make the plugin attempt to cache the statements result set, if any. A so-created cache entry is given the default TTL set with the PHP configuration directive mysqlnd_qc.ttl. If a different TTL shall be used, the callback returns a numeric value to be used as the TTL. The internal is_select function is part of the internal cache storage handler interface. Thus, a user-defined storage handler offers the same capabilities. Parameters This function has no parameters. Return Values Returns TRUE on success or FALSE on failure. Examples Example 22.314. mysqlnd_qc_set_is_selectexample <?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;}mysqlnd_qc_set_is_select("is_select");/* Connect, create and populate test table */$mysqli = new mysqli("host", "user", "password", "schema");$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");?> The above examples will output: 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): cache See Also 22.9.7.7.9. mysqlnd_qc_set_storage_handler Copyright 1997-2012 the PHP Documentation Group. Description bool mysqlnd_qc_set_storage_handler( string handler); Sets the storage handler used by the query cache. A list of available storage handler can be obtained from mysqlnd_qc_get_available_handlers. Which storage are available depends on the compile time configuration of the query cache plugin. The default storage handler is always available. All other storage handler must be enabled explicitly when building the extension. Parameters - handler
Handler can be of type string representing the name of a built-in storage handler or an object of type mysqlnd_qc_handler_default. The names of the built-in storage handler are default, APC, MEMCACHE, sqlite.
Return Values Returns TRUE on success or FALSE on failure. If changing the storage handler fails a catchable fatal error will be thrown. The query cache cannot operate if the previous storage handler has been shutdown but no new storage handler has been installed. Examples Example 22.315. mysqlnd_qc_set_storage_handlerexample The example shows the output from the built-in default storage handler. Other storage handler may report different data. <?phpvar_dump(mysqlnd_qc_set_storage_handler("memcache"));if (true === mysqlnd_qc_set_storage_handler("default")) printf("Default storage handler activated");/* Catchable fatal error */var_dump(mysqlnd_qc_set_storage_handler("unknown"));?> The above examples will output: bool(true)Default storage handler activatedCatchable fatal error: mysqlnd_qc_set_storage_handler(): Unknown handler 'unknown' in (file) on line (line) See Also 22.9.7.7.10. mysqlnd_qc_set_user_handlers Copyright 1997-2012 the PHP Documentation Group. Description bool mysqlnd_qc_set_user_handlers( string get_hash, string find_query_in_cache, string return_to_cache, string add_query_to_cache_if_not_exists, string query_is_select, string update_query_run_time_stats, string get_stats, string clear_cache); Sets the callback functions for a user-defined procedural storage handler. Parameters - get_hash
Name of the user function implementing the storage handler get_hash functionality. - find_query_in_cache
Name of the user function implementing the storage handler find_in_cache functionality. - return_to_cache
Name of the user function implementing the storage handler return_to_cache functionality. - add_query_to_cache_if_not_exists
Name of the user function implementing the storage handler add_query_to_cache_if_not_exists functionality. - query_is_select
Name of the user function implementing the storage handler query_is_select functionality. - update_query_run_time_stats
Name of the user function implementing the storage handler update_query_run_time_stats functionality. - get_stats
Name of the user function implementing the storage handler get_stats functionality. - clear_cache
Name of the user function implementing the storage handler clear_cache functionality.
Return Values Returns TRUE on success or FALSE on FAILURE. See Also Copyright 1997-2012 the PHP Documentation Group. This change history is a high level summary of selected changes that may impact applications and/or break backwards compatibility. See also the CHANGES file in the source distribution for a complete list of changes. 22.9.7.8.1. PECL/mysqlnd_qc 1.1 series Copyright 1997-2012 the PHP Documentation Group. 1.1.0 - Release date: under development
- Motto/theme: PHP 5.4 compatibility, schema pattern based caching and mysqlnd_ms support
Feature changes APC storage handler update - Fix build for APC 3.1.9+
- Note: Use of the APC storage handler is currently not recommended due to stability issues of APC itself.
New PHP configuration directives New constants and SQL hints New function mysqlnd_qc_set_cache_condition for built-in schema pattern based caching. Likely to support a wider range of conditions in the future. Report valid_until timestamp for cache entries of the default handler through mysqlnd_qc_get_cache_info. Include charset number for cache entry hashing. This should prevent serving result sets which have the wrong charset. API change: get_hash_key expects new "charsetnr" (int) parameter after "port". API change: changing is_select() signature from bool is_select() to mixed is_select(). Mixed can be either boolean or array(long ttl, string server_id). This is needed by PECL/mysqlnd_ms.
Other Bug fixes - Fixed Bug #59959 (config.m4, wrong library - 64bit memcached handler builds) (Credits: Remi Collet)
22.9.7.8.2. PECL/mysqlnd_qc 1.0 series Copyright 1997-2012 the PHP Documentation Group. 1.0.1-stable - Release date: 12/2010
- Motto/theme: Prepared statement support
Added support for Prepared statements and unbuffered queries. 1.0.0-beta - Release date: 07/2010
- Motto/theme: TTL-based cache with various storage options (Memcache, APC, SQLite, user-defined)
Initial public release of the transparent TTL-based query result cache. Flexible storage of cached results. Various storage media supported. Copyright © 1997, 2013, Oracle and/or its affiliates. All rights reserved. Legal Notices |
| |