MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sql_cache.h
1 /* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software Foundation,
14  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15 
16 #ifndef _SQL_CACHE_H
17 #define _SQL_CACHE_H
18 
19 #include "hash.h"
20 #include "my_base.h" /* ha_rows */
21 
22 class MY_LOCALE;
23 struct TABLE_LIST;
24 class Time_zone;
25 struct LEX;
26 struct TABLE;
28 typedef ulonglong sql_mode_t;
29 
30 /* Query cache */
31 
32 /*
33  Can't create new free memory block if unused memory in block less
34  then QUERY_CACHE_MIN_ALLOCATION_UNIT.
35  if QUERY_CACHE_MIN_ALLOCATION_UNIT == 0 then
36  QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automaticaly
37 */
38 #define QUERY_CACHE_MIN_ALLOCATION_UNIT 512
39 
40 /* inittial size of hashes */
41 #define QUERY_CACHE_DEF_QUERY_HASH_SIZE 1024
42 #define QUERY_CACHE_DEF_TABLE_HASH_SIZE 1024
43 
44 /* minimal result data size when data allocated */
45 #define QUERY_CACHE_MIN_RESULT_DATA_SIZE 1024*4
46 
47 /*
48  start estimation of first result block size only when number of queries
49  bigger then:
50 */
51 #define QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER 3
52 
53 
54 
55 /* memory bins size spacing (see at Query_cache::init_cache (sql_cache.cc)) */
56 #define QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2 4
57 #define QUERY_CACHE_MEM_BIN_STEP_PWR2 2
58 #define QUERY_CACHE_MEM_BIN_PARTS_INC 1
59 #define QUERY_CACHE_MEM_BIN_PARTS_MUL 1.2
60 #define QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2 3
61 
62 /* how many free blocks check when finding most suitable before other 'end'
63  of list of free blocks */
64 #define QUERY_CACHE_MEM_BIN_TRY 5
65 
66 /* packing parameters */
67 #define QUERY_CACHE_PACK_ITERATION 2
68 #define QUERY_CACHE_PACK_LIMIT (512*1024L)
69 
70 #define TABLE_COUNTER_TYPE uint
71 
72 struct Query_cache_block;
74 struct Query_cache_table;
75 struct Query_cache_query;
76 struct Query_cache_result;
77 class Query_cache;
78 struct Query_cache_tls;
79 struct LEX;
80 class THD;
81 
82 typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key,
83  uint key_length,
84  ulonglong *engine_data);
85 
94 {
95  Query_cache_block_table() {} /* Remove gcc warning */
96 
101  TABLE_COUNTER_TYPE n;
102 
108 
114 
121  inline Query_cache_block *block();
122 };
123 
125 {
126  Query_cache_block() {} /* Remove gcc warning */
127  enum block_type {FREE, QUERY, RESULT, RES_CONT, RES_BEG,
128  RES_INCOMPLETE, TABLE, INCOMPLETE};
129 
130  ulong length; // length of all block
131  ulong used; // length of data
132  /*
133  Not used **pprev, **prev because really needed access to pervious block:
134  *pprev to join free blocks
135  *prev to access to opposite side of list in cyclic sorted list
136  */
137  Query_cache_block *pnext,*pprev, // physical next/previous block
138  *next,*prev; // logical next/previous block
139  block_type type;
140  TABLE_COUNTER_TYPE n_tables; // number of tables in query
141 
142  inline my_bool is_free(void) { return type == FREE; }
143  void init(ulong length);
144  void destroy();
145  inline uint headers_len();
146  inline uchar* data(void);
147  inline Query_cache_query *query();
148  inline Query_cache_table *table();
149  inline Query_cache_result *result();
150  inline Query_cache_block_table *table(TABLE_COUNTER_TYPE n);
151 };
152 
154 {
155  ulonglong limit_found_rows;
156  mysql_rwlock_t lock;
157  Query_cache_block *res;
158  Query_cache_tls *wri;
159  ulong len;
160  uint8 tbls_type;
161  unsigned int last_pkt_nr;
162 
163  Query_cache_query() {} /* Remove gcc warning */
164  inline void init_n_lock();
165  void unlock_n_destroy();
166  inline ulonglong found_rows() { return limit_found_rows; }
167  inline void found_rows(ulonglong rows) { limit_found_rows= rows; }
168  inline Query_cache_block *result() { return res; }
169  inline void result(Query_cache_block *p) { res= p; }
170  inline Query_cache_tls *writer() { return wri; }
171  inline void writer(Query_cache_tls *p) { wri= p; }
172  inline uint8 tables_type() { return tbls_type; }
173  inline void tables_type(uint8 type) { tbls_type= type; }
174  inline ulong length() { return len; }
175  inline ulong add(ulong packet_len) { return(len+= packet_len); }
176  inline void length(ulong length_arg) { len= length_arg; }
177  inline uchar* query()
178  {
179  return (((uchar*)this) + ALIGN_SIZE(sizeof(Query_cache_query)));
180  }
181  void lock_writing();
182  void lock_reading();
183  my_bool try_lock_writing();
184  void unlock_writing();
185  void unlock_reading();
186 };
187 
188 
190 {
191  Query_cache_table() {} /* Remove gcc warning */
192  char *tbl;
193  uint32 key_len;
194  uint8 table_type;
195  /* unique for every engine reference */
196  qc_engine_callback callback_func;
197  /* data need by some engines */
198  ulonglong engine_data_buff;
199 
204 
205  inline char *db() { return (char *) data(); }
206  inline char *table() { return tbl; }
207  inline void table(char *table_arg) { tbl= table_arg; }
208  inline uint32 key_length() { return key_len; }
209  inline void key_length(uint32 len) { key_len= len; }
210  inline uint8 type() { return table_type; }
211  inline void type(uint8 t) { table_type= t; }
212  inline qc_engine_callback callback() { return callback_func; }
213  inline void callback(qc_engine_callback fn){ callback_func= fn; }
214  inline ulonglong engine_data() { return engine_data_buff; }
215  inline void engine_data(ulonglong data_arg){ engine_data_buff= data_arg; }
216  inline uchar* data()
217  {
218  return (uchar*)(((uchar*)this)+
219  ALIGN_SIZE(sizeof(Query_cache_table)));
220  }
221 };
222 
224 {
225  Query_cache_result() {} /* Remove gcc warning */
227 
228  inline uchar* data()
229  {
230  return (uchar*)(((uchar*) this)+
231  ALIGN_SIZE(sizeof(Query_cache_result)));
232  }
233  /* data_continue (if not whole packet contained by this block) */
234  inline Query_cache_block *parent() { return query; }
235  inline void parent (Query_cache_block *p) { query=p; }
236 };
237 
238 
239 extern "C"
240 {
241  uchar *query_cache_query_get_key(const uchar *record, size_t *length,
242  my_bool not_used);
243  uchar *query_cache_table_get_key(const uchar *record, size_t *length,
244  my_bool not_used);
245 }
246 extern "C" void query_cache_invalidate_by_MyISAM_filename(const char* filename);
247 
248 
250 {
251  Query_cache_memory_bin() {} /* Remove gcc warning */
252 #ifndef DBUG_OFF
253  ulong size;
254 #endif
255  uint number;
256  Query_cache_block *free_blocks;
257 
258  inline void init(ulong size_arg)
259  {
260 #ifndef DBUG_OFF
261  size = size_arg;
262 #endif
263  number = 0;
264  free_blocks = 0;
265  }
266 };
267 
269 {
270  Query_cache_memory_bin_step() {} /* Remove gcc warning */
271  ulong size;
272  ulong increment;
273  uint idx;
274  inline void init(ulong size_arg, uint idx_arg, ulong increment_arg)
275  {
276  size = size_arg;
277  idx = idx_arg;
278  increment = increment_arg;
279  }
280 };
281 
283 {
284 public:
285  /* Info */
286  ulong query_cache_size, query_cache_limit;
287  /* statistics */
288  ulong free_memory, queries_in_cache, hits, inserts, refused,
289  free_memory_blocks, total_blocks, lowmem_prunes;
290 
291 
292 private:
293 #ifndef DBUG_OFF
294  my_thread_id m_cache_lock_thread_id;
295 #endif
296  mysql_cond_t COND_cache_status_changed;
297  enum Cache_lock_status { UNLOCKED, LOCKED_NO_WAIT, LOCKED };
298  Cache_lock_status m_cache_lock_status;
299 
300  bool m_query_cache_is_disabled;
301 
302  void free_query_internal(Query_cache_block *point);
303  void invalidate_table_internal(THD *thd, uchar *key, uint32 key_length);
304  void disable_query_cache(void) { m_query_cache_is_disabled= TRUE; }
305 
306 protected:
307  /*
308  The following mutex is locked when searching or changing global
309  query, tables lists or hashes. When we are operating inside the
310  query structure we locked an internal query block mutex.
311  LOCK SEQUENCE (to prevent deadlocks):
312  1. structure_guard_mutex
313  2. query block (for operation inside query (query block/results))
314 
315  Thread doing cache flush releases the mutex once it sets
316  m_cache_status flag, so other threads may bypass the cache as
317  if it is disabled, not waiting for reset to finish. The exception
318  is other threads that were going to do cache flush---they'll wait
319  till the end of a flush operation.
320  */
321  mysql_mutex_t structure_guard_mutex;
322  uchar *cache; // cache memory
323  Query_cache_block *first_block; // physical location block list
324  Query_cache_block *queries_blocks; // query list (LIFO)
325  Query_cache_block *tables_blocks;
326 
327  Query_cache_memory_bin *bins; // free block lists
328  Query_cache_memory_bin_step *steps; // bins spacing info
329  HASH queries, tables;
330  /* options */
331  ulong min_allocation_unit, min_result_data_size;
332  uint def_query_hash_size, def_table_hash_size;
333 
334  uint mem_bin_num, mem_bin_steps; // See at init_cache & find_bin
335 
336  my_bool initialized;
337 
338  /* Exclude/include from cyclic double linked list */
339  static void double_linked_list_exclude(Query_cache_block *point,
340  Query_cache_block **list_pointer);
341  static void double_linked_list_simple_include(Query_cache_block *point,
343  list_pointer);
344  static void double_linked_list_join(Query_cache_block *head_tail,
345  Query_cache_block *tail_head);
346 
347  /* Table key generation */
348  static uint filename_2_table_key (char *key, const char *filename,
349  uint32 *db_langth);
350 
351  /* The following functions require that structure_guard_mutex is locked */
352  void flush_cache();
353  my_bool free_old_query();
354  void free_query(Query_cache_block *point);
355  my_bool allocate_data_chain(Query_cache_block **result_block,
356  ulong data_len,
357  Query_cache_block *query_block,
358  my_bool first_block);
359  void invalidate_table(THD *thd, TABLE_LIST *table);
360  void invalidate_table(THD *thd, TABLE *table);
361  void invalidate_table(THD *thd, uchar *key, uint32 key_length);
362  void invalidate_table(THD *thd, Query_cache_block *table_block);
363  void invalidate_query_block_list(THD *thd,
364  Query_cache_block_table *list_root);
365 
366  TABLE_COUNTER_TYPE
367  register_tables_from_list(TABLE_LIST *tables_used,
368  TABLE_COUNTER_TYPE counter,
369  Query_cache_block_table *block_table);
370  my_bool register_all_tables(Query_cache_block *block,
371  TABLE_LIST *tables_used,
372  TABLE_COUNTER_TYPE tables);
373  my_bool insert_table(uint key_len, const char *key,
375  uint32 db_length, uint8 cache_type,
376  qc_engine_callback callback,
377  ulonglong engine_data);
378  void unlink_table(Query_cache_block_table *node);
379  Query_cache_block *get_free_block (ulong len, my_bool not_less,
380  ulong min);
381  void free_memory_block(Query_cache_block *point);
382  void split_block(Query_cache_block *block, ulong len);
383  Query_cache_block *join_free_blocks(Query_cache_block *first_block,
384  Query_cache_block *block_in_list);
385  my_bool append_next_free_block(Query_cache_block *block,
386  ulong add_size);
387  void exclude_from_free_memory_list(Query_cache_block *free_block);
388  void insert_into_free_memory_list(Query_cache_block *new_block);
389  my_bool move_by_type(uchar **border, Query_cache_block **before,
390  ulong *gap, Query_cache_block *i);
391  uint find_bin(ulong size);
392  void move_to_query_list_end(Query_cache_block *block);
393  void insert_into_free_memory_sorted_list(Query_cache_block *new_block,
394  Query_cache_block **list);
395  void pack_cache();
396  void relink(Query_cache_block *oblock,
397  Query_cache_block *nblock,
398  Query_cache_block *next,
399  Query_cache_block *prev,
400  Query_cache_block *pnext,
401  Query_cache_block *pprev);
402  my_bool join_results(ulong join_limit);
403 
404  /*
405  Following function control structure_guard_mutex
406  by themself or don't need structure_guard_mutex
407  */
408  ulong init_cache();
409  void make_disabled();
410  void free_cache();
411  Query_cache_block *write_block_data(ulong data_len, uchar* data,
412  ulong header_len,
413  Query_cache_block::block_type type,
414  TABLE_COUNTER_TYPE ntab = 0);
415  my_bool append_result_data(Query_cache_block **result,
416  ulong data_len, uchar* data,
417  Query_cache_block *parent);
418  my_bool write_result_data(Query_cache_block **result,
419  ulong data_len, uchar* data,
420  Query_cache_block *parent,
421  Query_cache_block::block_type
422  type=Query_cache_block::RESULT);
423  inline ulong get_min_first_result_data_size();
424  inline ulong get_min_append_result_data_size();
425  Query_cache_block *allocate_block(ulong len, my_bool not_less,
426  ulong min);
427  /*
428  If query is cacheable return number tables in query
429  (query without tables not cached)
430  */
431  TABLE_COUNTER_TYPE is_cacheable(THD *thd, size_t query_len,
432  const char *query,
433  LEX *lex, TABLE_LIST *tables_used,
434  uint8 *tables_type);
435  TABLE_COUNTER_TYPE process_and_count_tables(THD *thd,
436  TABLE_LIST *tables_used,
437  uint8 *tables_type);
438 
439  static my_bool ask_handler_allowance(THD *thd, TABLE_LIST *tables_used);
440  public:
441 
442  Query_cache(ulong query_cache_limit = ULONG_MAX,
443  ulong min_allocation_unit = QUERY_CACHE_MIN_ALLOCATION_UNIT,
444  ulong min_result_data_size = QUERY_CACHE_MIN_RESULT_DATA_SIZE,
445  uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE,
446  uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE);
447 
448  bool is_disabled(void) { return m_query_cache_is_disabled; }
449 
450  /* initialize cache (mutex) */
451  void init();
452  /* resize query cache (return real query size, 0 if disabled) */
453  ulong resize(ulong query_cache_size);
454  /* set limit on result size */
455  inline void result_size_limit(ulong limit){query_cache_limit=limit;}
456  /* set minimal result data allocation unit size */
457  ulong set_min_res_unit(ulong size);
458 
459  /* register query in cache */
460  void store_query(THD *thd, TABLE_LIST *used_tables);
461 
462  /*
463  Check if the query is in the cache and if this is true send the
464  data to client.
465  */
466  int send_result_to_client(THD *thd, char *query, uint query_length);
467 
468  /* Remove all queries that uses any of the listed following tables */
469  void invalidate(THD* thd, TABLE_LIST *tables_used,
470  my_bool using_transactions);
471  void invalidate(CHANGED_TABLE_LIST *tables_used);
472  void invalidate_locked_for_write(TABLE_LIST *tables_used);
473  void invalidate(THD* thd, TABLE *table, my_bool using_transactions);
474  void invalidate(THD *thd, const char *key, uint32 key_length,
475  my_bool using_transactions);
476 
477  /* Remove all queries that uses any of the tables in following database */
478  void invalidate(char *db);
479 
480  /* Remove all queries that uses any of the listed following table */
481  void invalidate_by_MyISAM_filename(const char *filename);
482 
483  void flush();
484  void pack(ulong join_limit = QUERY_CACHE_PACK_LIMIT,
485  uint iteration_limit = QUERY_CACHE_PACK_ITERATION);
486 
487  void destroy();
488 
489  void insert(Query_cache_tls *query_cache_tls,
490  const char *packet,
491  ulong length,
492  unsigned pkt_nr);
493 
494  void end_of_result(THD *thd);
495  void abort(Query_cache_tls *query_cache_tls);
496 
497  /*
498  The following functions are only used when debugging
499  We don't protect these with ifndef DBUG_OFF to not have to recompile
500  everything if we want to add checks of the cache at some places.
501  */
502  void wreck(uint line, const char *message);
503  void bins_dump();
504  void cache_dump();
505  void queries_dump();
506  void tables_dump();
507  my_bool check_integrity(bool not_locked);
508  my_bool in_list(Query_cache_block * root, Query_cache_block * point,
509  const char *name);
510  my_bool in_table_list(Query_cache_block_table * root,
511  Query_cache_block_table * point,
512  const char *name);
513  my_bool in_blocks(Query_cache_block * point);
514 
515  bool try_lock(bool use_timeout= FALSE);
516  void lock(void);
517  void lock_and_suspend(void);
518  void unlock(void);
519 };
520 
521 #ifdef HAVE_QUERY_CACHE
522 struct Query_cache_query_flags
523 {
524  unsigned int client_long_flag:1;
525  unsigned int client_protocol_41:1;
526  unsigned int protocol_type:2;
527  unsigned int more_results_exists:1;
528  unsigned int in_trans:1;
529  unsigned int autocommit:1;
530  unsigned int pkt_nr;
531  uint character_set_client_num;
532  uint character_set_results_num;
533  uint collation_connection_num;
534  ha_rows limit;
535  Time_zone *time_zone;
536  sql_mode_t sql_mode;
537  ulong max_sort_length;
538  ulong group_concat_max_len;
539  ulong default_week_format;
540  ulong div_precision_increment;
541  MY_LOCALE *lc_time_names;
542 };
543 #define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags)
544 #include "sql_cache.h"
545 #define query_cache_abort(A) query_cache.abort(A)
546 #define query_cache_end_of_result(A) query_cache.end_of_result(A)
547 #define query_cache_store_query(A, B) query_cache.store_query(A, B)
548 #define query_cache_destroy() query_cache.destroy()
549 #define query_cache_result_size_limit(A) query_cache.result_size_limit(A)
550 #define query_cache_init() query_cache.init()
551 #define query_cache_resize(A) query_cache.resize(A)
552 #define query_cache_set_min_res_unit(A) query_cache.set_min_res_unit(A)
553 #define query_cache_invalidate3(A, B, C) query_cache.invalidate(A, B, C)
554 #define query_cache_invalidate1(A) query_cache.invalidate(A)
555 #define query_cache_send_result_to_client(A, B, C) \
556  query_cache.send_result_to_client(A, B, C)
557 #define query_cache_invalidate_by_MyISAM_filename_ref \
558  &query_cache_invalidate_by_MyISAM_filename
559 /* note the "maybe": it's a read without mutex */
560 #define query_cache_maybe_disabled(T) \
561  (T->variables.query_cache_type == 0 || query_cache.query_cache_size == 0)
562 #define query_cache_is_cacheable_query(L) \
563  (((L)->sql_command == SQLCOM_SELECT) && (L)->safe_to_cache_query && \
564  !(L)->describe)
565 #else
566 #define QUERY_CACHE_FLAGS_SIZE 0
567 #define query_cache_store_query(A, B)
568 #define query_cache_destroy()
569 #define query_cache_result_size_limit(A)
570 #define query_cache_init()
571 #define query_cache_resize(A)
572 #define query_cache_set_min_res_unit(A)
573 #define query_cache_invalidate3(A, B, C)
574 #define query_cache_invalidate1(A)
575 #define query_cache_send_result_to_client(A, B, C) 0
576 #define query_cache_invalidate_by_MyISAM_filename_ref NULL
577 
578 #define query_cache_abort(A)
579 #define query_cache_end_of_result(A)
580 #define query_cache_invalidate_by_MyISAM_filename_ref NULL
581 #define query_cache_maybe_disabled(T) 1
582 #define query_cache_is_cacheable_query(L) 0
583 #endif /*HAVE_QUERY_CACHE*/
584 
585 extern Query_cache query_cache;
586 #endif