[Commits] Rev 3702: MDEV-249 QUERY CACHE INFORMATION in http://bazaar.launchpad.net/~maria-captains/maria/5.5/

serg at askmonty.org serg at askmonty.org
Tue Mar 19 16:27:12 EET 2013


At http://bazaar.launchpad.net/~maria-captains/maria/5.5/

------------------------------------------------------------
revno: 3702
revision-id: sergii at pisem.net-20130319142705-km2hupyj83i6hzg8
parent: sergii at pisem.net-20130319142558-8saeg7054ros1rh9
fixes bug: https://mariadb.atlassian.net/browse/MDEV-249
committer: Sergei Golubchik <sergii at pisem.net>
branch nick: 5.5
timestamp: Tue 2013-03-19 15:27:05 +0100
message:
  MDEV-249 QUERY CACHE INFORMATION
-------------- next part --------------
=== added file 'mysql-test/suite/plugins/r/qc_info.result'
--- a/mysql-test/suite/plugins/r/qc_info.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/plugins/r/qc_info.result	2013-03-19 14:27:05 +0000
@@ -0,0 +1,15 @@
+set global query_cache_size=1355776;
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+select statement_schema, statement_text, result_blocks_count, result_blocks_size from information_schema.query_cache_info;
+statement_schema	statement_text	result_blocks_count	result_blocks_size
+test	select * from t1	1	512
+drop table t1;
+select statement_schema, statement_text, result_blocks_count, result_blocks_size from information_schema.query_cache_info;
+statement_schema	statement_text	result_blocks_count	result_blocks_size
+set global query_cache_size= default;

=== added file 'mysql-test/suite/plugins/r/qc_info_priv.result'
--- a/mysql-test/suite/plugins/r/qc_info_priv.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/plugins/r/qc_info_priv.result	2013-03-19 14:27:05 +0000
@@ -0,0 +1,23 @@
+set global query_cache_size=1355776;
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+select statement_schema, statement_text, result_blocks_count, result_blocks_size from information_schema.query_cache_info;
+statement_schema	statement_text	result_blocks_count	result_blocks_size
+test	select * from t1	1	512
+create user mysqltest;
+select a from t1;
+a
+1
+2
+3
+select count(*) from information_schema.query_cache_info;
+count(*)
+0
+drop user mysqltest;
+drop table t1;
+set global query_cache_size= default;

=== added file 'mysql-test/suite/plugins/t/qc_info.test'
--- a/mysql-test/suite/plugins/t/qc_info.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/plugins/t/qc_info.test	2013-03-19 14:27:05 +0000
@@ -0,0 +1,8 @@
+--source qc_info_init.inc
+
+drop table t1;
+# the query was invalidated
+select statement_schema, statement_text, result_blocks_count, result_blocks_size from information_schema.query_cache_info;
+
+set global query_cache_size= default;
+

=== added file 'mysql-test/suite/plugins/t/qc_info_init.inc'
--- a/mysql-test/suite/plugins/t/qc_info_init.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/plugins/t/qc_info_init.inc	2013-03-19 14:27:05 +0000
@@ -0,0 +1,12 @@
+if (`select count(*) = 0 from information_schema.plugins where plugin_name = 'query_cache_info' and plugin_status='active'`)
+{
+  --skip QUERY_CACHE_INFO plugin is not active
+}
+
+set global query_cache_size=1355776;
+
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+select * from t1;
+select statement_schema, statement_text, result_blocks_count, result_blocks_size from information_schema.query_cache_info;
+

=== added file 'mysql-test/suite/plugins/t/qc_info_init.opt'
--- a/mysql-test/suite/plugins/t/qc_info_init.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/plugins/t/qc_info_init.opt	2013-03-19 14:27:05 +0000
@@ -0,0 +1,2 @@
+--loose-query_cache_info
+--plugin-load=$QUERY_CACHE_INFO_SO

=== added file 'mysql-test/suite/plugins/t/qc_info_priv.test'
--- a/mysql-test/suite/plugins/t/qc_info_priv.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/plugins/t/qc_info_priv.test	2013-03-19 14:27:05 +0000
@@ -0,0 +1,15 @@
+--source include/not_embedded.inc
+--source qc_info_init.inc
+
+# try an unprivileged user
+create user mysqltest;
+connect (conn1,localhost,mysqltest,,);
+connection conn1;
+select a from t1;
+select count(*) from information_schema.query_cache_info;
+connection default;
+drop user mysqltest;
+drop table t1;
+
+set global query_cache_size= default;
+

=== modified file 'mysql-test/t/mysqld--help.test'
--- a/mysql-test/t/mysqld--help.test	2012-02-23 08:24:11 +0000
+++ b/mysql-test/t/mysqld--help.test	2013-03-19 14:27:05 +0000
@@ -23,8 +23,11 @@ perl;
                datadir slave-load-tmpdir tmpdir socket/;
 
   # Plugins which may or may not be there:
-  @plugins=qw/innodb ndb archive blackhole federated partition ndbcluster feedback debug temp-pool ssl des-key-file
-              xtradb thread-concurrency super-large-pages mutex-deadlock-detector null-audit maria aria pbxt oqgraph sphinx thread-handling thread-pool/;
+  @plugins=qw/innodb ndb archive blackhole federated partition ndbcluster
+              feedback debug temp-pool ssl des-key-file
+              xtradb thread-concurrency super-large-pages
+              mutex-deadlock-detector null-audit maria aria pbxt oqgraph
+              sphinx thread-handling thread-pool query-cache-info/;
 
   # And substitute the content some environment variables with their
   # names:

=== added directory 'plugin/qc_info'
=== added file 'plugin/qc_info/CMakeLists.txt'
--- a/plugin/qc_info/CMakeLists.txt	1970-01-01 00:00:00 +0000
+++ b/plugin/qc_info/CMakeLists.txt	2013-03-19 14:27:05 +0000
@@ -0,0 +1,10 @@
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/regex
+                    ${CMAKE_SOURCE_DIR}/extra/yassl/include)
+
+IF(WIN32)
+  MYSQL_ADD_PLUGIN(QUERY_CACHE_INFO qc_info.cc STATIC_ONLY
+    RECOMPILE_FOR_EMBEDDED)
+ELSE(WIN32)
+  MYSQL_ADD_PLUGIN(QUERY_CACHE_INFO qc_info.cc
+    RECOMPILE_FOR_EMBEDDED)
+ENDIF(WIN32)

=== added file 'plugin/qc_info/qc_info.cc'
--- a/plugin/qc_info/qc_info.cc	1970-01-01 00:00:00 +0000
+++ b/plugin/qc_info/qc_info.cc	2013-03-19 14:27:05 +0000
@@ -0,0 +1,207 @@
+/*
+  Copyright (c) 2008, Roland Bouman
+  http://rpbouman.blogspot.com/
+  roland.bouman at gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+      * Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+      * Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+      * Neither the name of the Roland Bouman nor the
+        names of the contributors may be used to endorse or promote products
+        derived from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * TODO: report query cache flags
+ */
+#ifndef MYSQL_SERVER
+#define MYSQL_SERVER
+#endif
+
+#include <sql_cache.h>
+#include <sql_parse.h>          // check_global_access
+#include <sql_acl.h>            // PROCESS_ACL
+#include <sql_class.h>          // THD
+#include <table.h>              // ST_SCHEMA_TABLE
+#include <mysql/plugin.h>
+
+class Accessible_Query_Cache : public Query_cache {
+public:
+  HASH *get_queries()
+  {
+    return &this->queries;
+  }
+};
+
+bool schema_table_store_record(THD *thd, TABLE *table);
+
+#define MAX_STATEMENT_TEXT_LENGTH 32767
+#define COLUMN_STATEMENT_SCHEMA 0
+#define COLUMN_STATEMENT_TEXT 1
+#define COLUMN_RESULT_BLOCKS_COUNT 2
+#define COLUMN_RESULT_BLOCKS_SIZE 3
+#define COLUMN_RESULT_BLOCKS_SIZE_USED 4
+
+/* ST_FIELD_INFO is defined in table.h */
+static ST_FIELD_INFO qc_info_fields[]=
+{
+  {"STATEMENT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+  {"STATEMENT_TEXT", MAX_STATEMENT_TEXT_LENGTH, MYSQL_TYPE_STRING, 0, 0, 0},
+  {"RESULT_BLOCKS_COUNT", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, 0},
+  {"RESULT_BLOCKS_SIZE", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, 0},
+  {"RESULT_BLOCKS_SIZE_USED", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, 0},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+static int qc_info_fill_table(THD *thd, TABLE_LIST *tables,
+                                              COND *cond)
+{
+  int status= 1;
+  CHARSET_INFO *scs= system_charset_info;
+  TABLE *table= tables->table;
+  Accessible_Query_Cache *qc = (Accessible_Query_Cache *)&query_cache;
+  HASH *queries = qc->get_queries();
+
+  /* one must have PROCESS privilege to see others' queries */
+  if (check_global_access(thd, PROCESS_ACL, true))
+    return 0;
+
+  if (qc->try_lock(thd))
+    return status;
+
+  /* loop through all queries in the query cache */
+  for (uint i= 0; i < queries->records; i++)
+  {
+    const uchar *query_cache_block_raw;
+    Query_cache_block* query_cache_block;
+    Query_cache_query* query_cache_query;
+    uint result_blocks_count;
+    ulonglong result_blocks_size;
+    ulonglong result_blocks_size_used;
+    Query_cache_block *first_result_block;
+    Query_cache_block *result_block;
+    const char *statement_text;
+    size_t statement_text_length;
+    const char *key, *db;
+    size_t key_length, db_length;
+
+    query_cache_block_raw = my_hash_element(queries, i);
+    query_cache_block = (Query_cache_block*)query_cache_block_raw;
+    if (query_cache_block->type != Query_cache_block::QUERY)
+      continue;
+
+    query_cache_query = query_cache_block->query();
+
+    /* Get the actual SQL statement for this query cache query */
+    statement_text = (const char*)query_cache_query->query();
+    statement_text_length = strlen(statement_text);
+    /* We truncate SQL statements up to MAX_STATEMENT_TEXT_LENGTH in our I_S table */
+    table->field[COLUMN_STATEMENT_TEXT]->store((char*)statement_text,
+           min(statement_text_length, MAX_STATEMENT_TEXT_LENGTH), scs);
+
+    /* get the entire key that identifies this query cache query */
+    key = (const char*)query_cache_query_get_key(query_cache_block_raw,
+                                                 &key_length, 0);
+    /* The database against which the statement is executed is part of the
+       query cache query key
+     */
+    compile_time_assert(QUERY_CACHE_DB_LENGTH_SIZE == 2); 
+    db= key + statement_text_length + 1 + QUERY_CACHE_DB_LENGTH_SIZE;
+    db_length= uint2korr(db - QUERY_CACHE_DB_LENGTH_SIZE);
+
+    table->field[COLUMN_STATEMENT_SCHEMA]->store(db, db_length, scs);
+
+    /* If we have result blocks, process them */
+    first_result_block= query_cache_query->result();
+    if(first_result_block)
+    {
+      /* initialize so we can loop over the result blocks*/
+      result_block= first_result_block;
+      result_blocks_count = 1;
+      result_blocks_size = result_block->length;
+      result_blocks_size_used = result_block->used;
+
+      /* loop over the result blocks*/
+      while((result_block= result_block->next)!=first_result_block)
+      {
+        /* calculate total number of result blocks */
+        result_blocks_count++;
+        /* calculate total size of result blocks */
+        result_blocks_size += result_block->length;
+        /* calculate total of used size of result blocks */
+        result_blocks_size_used += result_block->used;
+      }
+    }
+    else
+    {
+      result_blocks_count = 0;
+      result_blocks_size = 0;
+      result_blocks_size_used = 0;
+    }
+    table->field[COLUMN_RESULT_BLOCKS_COUNT]->store(result_blocks_count, 0);
+    table->field[COLUMN_RESULT_BLOCKS_SIZE]->store(result_blocks_size, 0);
+    table->field[COLUMN_RESULT_BLOCKS_SIZE_USED]->store(result_blocks_size_used, 0);
+
+    if (schema_table_store_record(thd, table))
+      goto cleanup;
+  }
+  status = 0;
+
+cleanup:
+  qc->unlock();
+  return status;
+}
+
+static int qc_info_plugin_init(void *p)
+{
+  ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p;
+
+  schema->fields_info= qc_info_fields;
+  schema->fill_table= qc_info_fill_table;
+
+  return 0;
+}
+
+
+static struct st_mysql_information_schema qc_info_plugin=
+{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
+
+/*
+  Plugin library descriptor
+*/
+
+maria_declare_plugin(query_cache_info)
+{
+  MYSQL_INFORMATION_SCHEMA_PLUGIN,
+  &qc_info_plugin,
+  "QUERY_CACHE_INFO",
+  "Roland Bouman",
+  "Lists all queries in the query cache.",
+  PLUGIN_LICENSE_BSD,
+  qc_info_plugin_init, /* Plugin Init */
+  0,                          /* Plugin Deinit        */
+  0x0100,                     /* version, hex         */
+  NULL,                       /* status variables     */
+  NULL,                       /* system variables     */
+  "1.0",                      /* version as a string  */
+  MariaDB_PLUGIN_MATURITY_ALPHA
+}
+maria_declare_plugin_end;
+

=== modified file 'sql/sql_cache.cc'
--- a/sql/sql_cache.cc	2013-02-28 21:47:29 +0000
+++ b/sql/sql_cache.cc	2013-03-19 14:27:05 +0000
@@ -828,18 +828,18 @@ void Query_cache_block::destroy()
   DBUG_VOID_RETURN;
 }
 
-inline uint Query_cache_block::headers_len()
+uint Query_cache_block::headers_len()
 {
   return (ALIGN_SIZE(sizeof(Query_cache_block_table)*n_tables) +
 	  ALIGN_SIZE(sizeof(Query_cache_block)));
 }
 
-inline uchar* Query_cache_block::data(void)
+uchar* Query_cache_block::data(void)
 {
   return (uchar*)( ((uchar*)this) + headers_len() );
 }
 
-inline Query_cache_query * Query_cache_block::query()
+Query_cache_query * Query_cache_block::query()
 {
 #ifndef DBUG_OFF
   if (type != QUERY)
@@ -848,7 +848,7 @@ inline Query_cache_query * Query_cache_b
   return (Query_cache_query *) data();
 }
 
-inline Query_cache_table * Query_cache_block::table()
+Query_cache_table * Query_cache_block::table()
 {
 #ifndef DBUG_OFF
   if (type != TABLE)
@@ -857,7 +857,7 @@ inline Query_cache_table * Query_cache_b
   return (Query_cache_table *) data();
 }
 
-inline Query_cache_result * Query_cache_block::result()
+Query_cache_result * Query_cache_block::result()
 {
 #ifndef DBUG_OFF
   if (type != RESULT && type != RES_CONT && type != RES_BEG &&
@@ -867,7 +867,7 @@ inline Query_cache_result * Query_cache_
   return (Query_cache_result *) data();
 }
 
-inline Query_cache_block_table * Query_cache_block::table(TABLE_COUNTER_TYPE n)
+Query_cache_block_table * Query_cache_block::table(TABLE_COUNTER_TYPE n)
 {
   return ((Query_cache_block_table *)
 	  (((uchar*)this)+ALIGN_SIZE(sizeof(Query_cache_block)) +

=== modified file 'sql/sql_cache.h'
--- a/sql/sql_cache.h	2012-07-13 19:17:32 +0000
+++ b/sql/sql_cache.h	2013-03-19 14:27:05 +0000
@@ -141,12 +141,12 @@ struct Query_cache_block
   inline bool is_free(void) { return type == FREE; }
   void init(ulong length);
   void destroy();
-  inline uint headers_len();
-  inline uchar* data(void);
-  inline Query_cache_query *query();
-  inline Query_cache_table *table();
-  inline Query_cache_result *result();
-  inline Query_cache_block_table *table(TABLE_COUNTER_TYPE n);
+  uint headers_len();
+  uchar* data(void);
+  Query_cache_query *query();
+  Query_cache_table *table();
+  Query_cache_result *result();
+  Query_cache_block_table *table(TABLE_COUNTER_TYPE n);
 };
 
 struct Query_cache_query



More information about the commits mailing list