330 #include "my_global.h"
332 #include "sql_cache.h"
333 #include "sql_parse.h"
336 #include "sql_base.h"
339 #include "sql_table.h"
340 #ifdef HAVE_QUERY_CACHE
344 #include "../storage/myisammrg/ha_myisammrg.h"
345 #include "../storage/myisammrg/myrg_def.h"
346 #include "probes_mysql.h"
347 #include "transaction.h"
349 #ifdef EMBEDDED_LIBRARY
350 #include "emb_qcache.h"
356 #if !defined(EXTRA_DBUG) && !defined(DBUG_OFF)
357 #define RW_WLOCK(M) {DBUG_PRINT("lock", ("rwlock wlock 0x%lx",(ulong)(M))); \
358 if (!mysql_rwlock_wrlock(M)) DBUG_PRINT("lock", ("rwlock wlock ok")); \
359 else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); }
360 #define RW_RLOCK(M) {DBUG_PRINT("lock", ("rwlock rlock 0x%lx", (ulong)(M))); \
361 if (!mysql_rwlock_rdlock(M)) DBUG_PRINT("lock", ("rwlock rlock ok")); \
362 else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); }
363 #define RW_UNLOCK(M) {DBUG_PRINT("lock", ("rwlock unlock 0x%lx",(ulong)(M))); \
364 if (!mysql_rwlock_unlock(M)) DBUG_PRINT("lock", ("rwlock unlock ok")); \
365 else DBUG_PRINT("lock", ("rwlock unlock FAILED %d", errno)); }
366 #define BLOCK_LOCK_WR(B) {DBUG_PRINT("lock", ("%d LOCK_WR 0x%lx",\
367 __LINE__,(ulong)(B))); \
368 B->query()->lock_writing();}
369 #define BLOCK_LOCK_RD(B) {DBUG_PRINT("lock", ("%d LOCK_RD 0x%lx",\
370 __LINE__,(ulong)(B))); \
371 B->query()->lock_reading();}
372 #define BLOCK_UNLOCK_WR(B) { \
373 DBUG_PRINT("lock", ("%d UNLOCK_WR 0x%lx",\
374 __LINE__,(ulong)(B)));B->query()->unlock_writing();}
375 #define BLOCK_UNLOCK_RD(B) { \
376 DBUG_PRINT("lock", ("%d UNLOCK_RD 0x%lx",\
377 __LINE__,(ulong)(B)));B->query()->unlock_reading();}
378 #define DUMP(C) DBUG_EXECUTE("qcache", {\
379 (C)->cache_dump(); (C)->queries_dump();(C)->tables_dump();})
381 #define RW_WLOCK(M) mysql_rwlock_wrlock(M)
382 #define RW_RLOCK(M) mysql_rwlock_rdlock(M)
383 #define RW_UNLOCK(M) mysql_rwlock_unlock(M)
384 #define BLOCK_LOCK_WR(B) B->query()->lock_writing()
385 #define BLOCK_LOCK_RD(B) B->query()->lock_reading()
386 #define BLOCK_UNLOCK_WR(B) B->query()->unlock_writing()
387 #define BLOCK_UNLOCK_RD(B) B->query()->unlock_reading()
396 #if defined(ENABLED_DEBUG_SYNC)
397 #define QC_DEBUG_SYNC(name) \
399 THD *thd= current_thd; \
401 DEBUG_SYNC(thd, name); \
404 #define QC_DEBUG_SYNC(name)
413 struct Query_cache_wait_state
421 Query_cache_wait_state(THD *thd,
const char *func,
422 const char *
file,
unsigned int line)
425 m_func(func), m_file(file), m_line(line)
428 set_thd_stage_info(m_thd,
429 &stage_waiting_for_query_cache_lock,
431 m_func, m_file, m_line);
434 ~Query_cache_wait_state()
437 set_thd_stage_info(m_thd, &m_old_stage, NULL, m_func, m_file, m_line);
460 bool Query_cache::try_lock(
bool use_timeout)
462 bool interrupt= FALSE;
463 THD *thd= current_thd;
464 Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
465 DBUG_ENTER(
"Query_cache::try_lock");
470 if (m_cache_lock_status == Query_cache::UNLOCKED)
472 m_cache_lock_status= Query_cache::LOCKED;
475 m_cache_lock_thread_id= thd->thread_id;
479 else if (m_cache_lock_status == Query_cache::LOCKED_NO_WAIT)
490 DBUG_ASSERT(m_cache_lock_status == Query_cache::LOCKED);
498 set_timespec_nsec(waittime,(ulong)(50000000L));
500 &structure_guard_mutex, &waittime);
501 if (res == ETIMEDOUT)
515 DBUG_RETURN(interrupt);
530 void Query_cache::lock_and_suspend(
void)
532 THD *thd= current_thd;
533 Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
534 DBUG_ENTER(
"Query_cache::lock_and_suspend");
537 while (m_cache_lock_status != Query_cache::UNLOCKED)
539 m_cache_lock_status= Query_cache::LOCKED_NO_WAIT;
542 m_cache_lock_thread_id= thd->thread_id;
559 void Query_cache::lock(
void)
561 THD *thd= current_thd;
562 Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
563 DBUG_ENTER(
"Query_cache::lock");
566 while (m_cache_lock_status != Query_cache::UNLOCKED)
568 m_cache_lock_status= Query_cache::LOCKED;
571 m_cache_lock_thread_id= thd->thread_id;
583 void Query_cache::unlock(
void)
585 DBUG_ENTER(
"Query_cache::unlock");
588 THD *thd= current_thd;
590 DBUG_ASSERT(m_cache_lock_thread_id == thd->thread_id);
592 DBUG_ASSERT(m_cache_lock_status == Query_cache::LOCKED ||
593 m_cache_lock_status == Query_cache::LOCKED_NO_WAIT);
594 m_cache_lock_status= Query_cache::UNLOCKED;
595 DBUG_PRINT(
"Query_cache",(
"Sending signal"));
613 static bool has_no_cache_directive(
char *sql)
616 while (sql[i] ==
' ')
619 if (my_toupper(system_charset_info, sql[i]) ==
'S' &&
620 my_toupper(system_charset_info, sql[i+1]) ==
'Q' &&
621 my_toupper(system_charset_info, sql[i+2]) ==
'L' &&
622 my_toupper(system_charset_info, sql[i+3]) ==
'_' &&
623 my_toupper(system_charset_info, sql[i+4]) ==
'N' &&
624 my_toupper(system_charset_info, sql[i+5]) ==
'O' &&
625 my_toupper(system_charset_info, sql[i+6]) ==
'_' &&
626 my_toupper(system_charset_info, sql[i+7]) ==
'C' &&
627 my_toupper(system_charset_info, sql[i+8]) ==
'A' &&
628 my_toupper(system_charset_info, sql[i+9]) ==
'C' &&
629 my_toupper(system_charset_info, sql[i+10]) ==
'H' &&
630 my_toupper(system_charset_info, sql[i+11]) ==
'E' &&
631 my_toupper(system_charset_info, sql[i+12]) ==
' ')
653 void Query_cache_block::init(ulong block_length)
655 DBUG_ENTER(
"Query_cache_block::init");
656 DBUG_PRINT(
"qcache", (
"init block: 0x%lx length: %lu", (ulong)
this,
658 length = block_length;
660 type = Query_cache_block::FREE;
665 void Query_cache_block::destroy()
667 DBUG_ENTER(
"Query_cache_block::destroy");
668 DBUG_PRINT(
"qcache", (
"destroy block 0x%lx, type %d",
669 (ulong)
this,
type));
674 inline uint Query_cache_block::headers_len()
680 inline uchar* Query_cache_block::data(
void)
682 return (uchar*)( ((uchar*)
this) + headers_len() );
689 query_cache.wreck(__LINE__,
"incorrect block type");
698 query_cache.wreck(__LINE__,
"incorrect block type");
706 if (
type != RESULT &&
type != RES_CONT &&
type != RES_BEG &&
707 type != RES_INCOMPLETE)
708 query_cache.wreck(__LINE__,
"incorrect block type");
727 uchar *query_cache_table_get_key(
const uchar *
record,
size_t *length,
728 my_bool not_used __attribute__((unused)))
731 *length = (table_block->used - table_block->headers_len() -
733 return (((uchar *) table_block->data()) +
750 inline void Query_cache_query::lock_writing()
763 my_bool Query_cache_query::try_lock_writing()
765 DBUG_ENTER(
"Query_cache_block::try_lock_writing");
768 DBUG_PRINT(
"info", (
"can't lock rwlock"));
771 DBUG_PRINT(
"info", (
"rwlock 0x%lx locked", (ulong) &lock));
776 inline void Query_cache_query::lock_reading()
782 inline void Query_cache_query::unlock_writing()
788 inline void Query_cache_query::unlock_reading()
794 void Query_cache_query::init_n_lock()
796 DBUG_ENTER(
"Query_cache_query::init_n_lock");
797 res=0; wri = 0; len = 0;
800 DBUG_PRINT(
"qcache", (
"inited & locked query for block 0x%lx",
801 (
long) (((uchar*)
this) -
807 void Query_cache_query::unlock_n_destroy()
809 DBUG_ENTER(
"Query_cache_query::unlock_n_destroy");
810 DBUG_PRINT(
"qcache", (
"destroyed & unlocked query for block 0x%lx",
811 (
long) (((uchar*)
this) -
817 this->unlock_writing();
825 uchar *query_cache_query_get_key(
const uchar *record,
size_t *length,
829 *length = (query_block->used - query_block->headers_len() -
831 return (((uchar *) query_block->data()) +
873 void query_cache_insert(
const char *packet, ulong length,
876 THD *thd= current_thd;
888 query_cache.insert(&thd->query_cache_tls,
900 const char *packet, ulong length,
903 DBUG_ENTER(
"Query_cache::insert");
906 if (is_disabled() || query_cache_tls->first_query_block == NULL)
909 QC_DEBUG_SYNC(
"wait_in_query_cache_insert");
915 if (query_block == NULL)
924 BLOCK_LOCK_WR(query_block);
929 DBUG_PRINT(
"qcache", (
"insert packet %lu bytes long",length));
936 if (!append_result_data(&result, length, (uchar*) packet,
939 DBUG_PRINT(
"warning", (
"Can't append data"));
940 header->result(result);
941 DBUG_PRINT(
"qcache", (
"free query 0x%lx", (ulong) query_block));
943 query_cache.free_query(query_block);
944 query_cache.refused++;
950 header->result(result);
951 header->last_pkt_nr= pkt_nr;
952 BLOCK_UNLOCK_WR(query_block);
953 DBUG_EXECUTE(
"check_querycache",check_integrity(0););
962 DBUG_ENTER(
"query_cache_abort");
963 THD *thd= current_thd;
966 if (is_disabled() || query_cache_tls->first_query_block == NULL)
979 THD_STAGE_INFO(thd, stage_storing_result_in_query_cache);
981 BLOCK_LOCK_WR(query_block);
983 free_query(query_block);
984 query_cache_tls->first_query_block= NULL;
985 DBUG_EXECUTE(
"check_querycache", check_integrity(1););
994 void Query_cache::end_of_result(THD *thd)
998 ulonglong limit_found_rows= thd->limit_found_rows;
999 DBUG_ENTER(
"Query_cache::end_of_result");
1002 if (query_cache_tls->first_query_block == NULL)
1005 if (thd->killed || thd->is_error())
1007 query_cache_abort(&thd->query_cache_tls);
1012 DBUG_ASSERT(thd->get_stmt_da()->is_eof());
1014 #ifdef EMBEDDED_LIBRARY
1015 insert(query_cache_tls, (
char*)thd,
1016 emb_count_querycache_size(thd), 0);
1022 query_block= query_cache_tls->first_query_block;
1030 THD_STAGE_INFO(thd, stage_storing_result_in_query_cache);
1032 BLOCK_LOCK_WR(query_block);
1038 if (header->result() == 0)
1040 DBUG_PRINT(
"error", (
"End of data with no result blocks; "
1041 "Query '%s' removed from cache.", header->query()));
1048 free_query(query_block);
1052 last_result_block= header->result()->prev;
1053 allign_size= ALIGN_SIZE(last_result_block->used);
1054 len= max(query_cache.min_allocation_unit, allign_size);
1055 if (last_result_block->length >= query_cache.min_allocation_unit + len)
1056 query_cache.split_block(last_result_block,len);
1058 header->found_rows(limit_found_rows);
1059 header->result()->type= Query_cache_block::RESULT;
1063 query_cache_tls->first_query_block= NULL;
1064 BLOCK_UNLOCK_WR(query_block);
1065 DBUG_EXECUTE(
"check_querycache", check_integrity(1););
1072 void query_cache_invalidate_by_MyISAM_filename(
const char *filename)
1074 query_cache.invalidate_by_MyISAM_filename(filename);
1075 DBUG_EXECUTE(
"check_querycache",query_cache.check_integrity(0););
1083 void mysql_query_cache_invalidate4(THD *thd,
1084 const char *key,
unsigned key_length,
1087 query_cache.invalidate(thd, key, (uint32) key_length, (my_bool) using_trx);
1095 Query_cache::Query_cache(ulong query_cache_limit_arg,
1096 ulong min_allocation_unit_arg,
1097 ulong min_result_data_size_arg,
1098 uint def_query_hash_size_arg,
1099 uint def_table_hash_size_arg)
1100 :query_cache_size(0),
1101 query_cache_limit(query_cache_limit_arg),
1102 queries_in_cache(0), hits(0), inserts(0), refused(0),
1103 total_blocks(0), lowmem_prunes(0), m_query_cache_is_disabled(FALSE),
1104 min_allocation_unit(ALIGN_SIZE(min_allocation_unit_arg)),
1105 min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)),
1106 def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)),
1107 def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)),
1113 set_if_bigger(min_allocation_unit,min_needed);
1114 this->min_allocation_unit= ALIGN_SIZE(min_allocation_unit);
1115 set_if_bigger(this->min_result_data_size,min_allocation_unit);
1119 ulong Query_cache::resize(ulong query_cache_size_arg)
1121 ulong new_query_cache_size;
1122 DBUG_ENTER(
"Query_cache::resize");
1123 DBUG_PRINT(
"qcache", (
"from %lu to %lu",query_cache_size,
1124 query_cache_size_arg));
1125 DBUG_ASSERT(initialized);
1138 BLOCK_LOCK_WR(block);
1140 if (query->writer())
1146 query->writer()->first_query_block= NULL;
1150 query->unlock_n_destroy();
1152 }
while (block != queries_blocks);
1156 query_cache_size= query_cache_size_arg;
1157 new_query_cache_size= init_cache();
1159 if (new_query_cache_size)
1160 DBUG_EXECUTE(
"check_querycache",check_integrity(1););
1163 DBUG_RETURN(new_query_cache_size);
1167 ulong Query_cache::set_min_res_unit(ulong
size)
1169 if (size < min_allocation_unit)
1170 size= min_allocation_unit;
1171 return (min_result_data_size= ALIGN_SIZE(size));
1175 void Query_cache::store_query(THD *thd,
TABLE_LIST *tables_used)
1177 TABLE_COUNTER_TYPE local_tables;
1179 DBUG_ENTER(
"Query_cache::store_query");
1188 if (thd->locked_tables_mode || query_cache_size == 0)
1191 #ifndef EMBEDDED_LIBRARY
1198 if (thd->net.vio == NULL)
1202 uint8 tables_type= 0;
1204 if ((local_tables= is_cacheable(thd, thd->query_length(),
1205 thd->query(), thd->lex, tables_used,
1208 NET *net= &thd->net;
1209 Query_cache_query_flags
flags;
1211 memset(&flags, 0, QUERY_CACHE_FLAGS_SIZE);
1212 flags.client_long_flag=
test(thd->client_capabilities & CLIENT_LONG_FLAG);
1213 flags.client_protocol_41=
test(thd->client_capabilities &
1214 CLIENT_PROTOCOL_41);
1220 flags.protocol_type= (
unsigned int) thd->protocol->type();
1222 DBUG_ASSERT(flags.protocol_type != (
unsigned int) Protocol::PROTOCOL_LOCAL);
1223 flags.more_results_exists=
test(thd->server_status &
1224 SERVER_MORE_RESULTS_EXISTS);
1225 flags.in_trans= thd->in_active_multi_stmt_transaction();
1226 flags.autocommit=
test(thd->server_status & SERVER_STATUS_AUTOCOMMIT);
1227 flags.pkt_nr= net->pkt_nr;
1228 flags.character_set_client_num=
1229 thd->variables.character_set_client->number;
1230 flags.character_set_results_num=
1231 (thd->variables.character_set_results ?
1232 thd->variables.character_set_results->number :
1234 flags.collation_connection_num=
1235 thd->variables.collation_connection->number;
1236 flags.limit= thd->variables.select_limit;
1237 flags.time_zone= thd->variables.time_zone;
1238 flags.sql_mode= thd->variables.sql_mode;
1239 flags.max_sort_length= thd->variables.max_sort_length;
1240 flags.lc_time_names= thd->variables.lc_time_names;
1241 flags.group_concat_max_len= thd->variables.group_concat_max_len;
1242 flags.div_precision_increment= thd->variables.div_precincrement;
1243 flags.default_week_format= thd->variables.default_week_format;
1244 DBUG_PRINT(
"qcache", (
"\
1245 long %d, 4.1: %d, bin_proto: %d, more results %d, pkt_nr: %d, \
1246 CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
1247 sql mode: 0x%llx, sort len: %lu, conncat len: %lu, div_precision: %lu, \
1248 def_week_frmt: %lu, in_trans: %d, autocommit: %d",
1249 (
int)flags.client_long_flag,
1250 (
int)flags.client_protocol_41,
1251 (
int)flags.protocol_type,
1252 (
int)flags.more_results_exists,
1254 flags.character_set_client_num,
1255 flags.character_set_results_num,
1256 flags.collation_connection_num,
1257 (ulong) flags.limit,
1258 (ulong) flags.time_zone,
1260 flags.max_sort_length,
1261 flags.group_concat_max_len,
1262 flags.div_precision_increment,
1263 flags.default_week_format,
1264 (
int)flags.in_trans,
1265 (
int)flags.autocommit));
1286 if (query_cache_size == 0)
1293 if (ask_handler_allowance(thd, tables_used))
1303 memcpy(thd->query() + thd->query_length() + 1 +
sizeof(size_t),
1304 thd->db, thd->db_length);
1305 DBUG_PRINT(
"qcache", (
"database: %s length: %u",
1306 thd->db, (
unsigned) thd->db_length));
1310 DBUG_PRINT(
"qcache", (
"No active database"));
1312 tot_length= thd->query_length() + thd->db_length + 1 +
1313 sizeof(size_t) + QUERY_CACHE_FLAGS_SIZE;
1318 memcpy((
void*) (thd->query() + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
1319 &
flags, QUERY_CACHE_FLAGS_SIZE);
1323 my_hash_search(&queries, (uchar*) thd->query(), tot_length);
1324 DBUG_PRINT(
"qcache", (
"competitor 0x%lx", (ulong) competitor));
1325 if (competitor == 0)
1329 query_block= write_block_data(tot_length, (uchar*) thd->query(),
1331 Query_cache_block::QUERY, local_tables);
1332 if (query_block != 0)
1334 DBUG_PRINT(
"qcache", (
"query block 0x%lx allocated, %lu",
1335 (ulong) query_block, query_block->used));
1338 header->init_n_lock();
1339 if (my_hash_insert(&queries, (uchar*) query_block))
1342 DBUG_PRINT(
"qcache", (
"insertion in query hash"));
1343 header->unlock_n_destroy();
1344 free_memory_block(query_block);
1348 if (!register_all_tables(query_block, tables_used, local_tables))
1351 DBUG_PRINT(
"warning", (
"tables list including failed"));
1352 my_hash_delete(&queries, (uchar *) query_block);
1353 header->unlock_n_destroy();
1354 free_memory_block(query_block);
1358 double_linked_list_simple_include(query_block, &queries_blocks);
1361 thd->query_cache_tls.first_query_block= query_block;
1362 header->writer(&thd->query_cache_tls);
1363 header->tables_type(tables_type);
1368 BLOCK_UNLOCK_WR(query_block);
1375 DBUG_PRINT(
"warning", (
"Can't allocate query"));
1383 DBUG_PRINT(
"qcache", (
"Another thread process same query"));
1386 else if (thd->lex->sql_command == SQLCOM_SELECT)
1387 statistic_increment(refused, &structure_guard_mutex);
1394 #ifndef EMBEDDED_LIBRARY
1412 send_data_in_chunks(
NET *net,
const uchar *packet, ulong len)
1428 static const ulong MAX_CHUNK_LENGTH= 1024*1024;
1430 while (len > MAX_CHUNK_LENGTH)
1434 packet+= MAX_CHUNK_LENGTH;
1435 len-= MAX_CHUNK_LENGTH;
1465 Query_cache::send_result_to_client(THD *thd,
char *sql, uint query_length)
1467 ulonglong engine_data;
1469 #ifndef EMBEDDED_LIBRARY
1475 Query_cache_query_flags
flags;
1476 enum xa_states xa_state= thd->transaction.xid_state.xa_state;
1477 DBUG_ENTER(
"Query_cache::send_result_to_client");
1486 if (is_disabled() || thd->locked_tables_mode ||
1487 thd->variables.query_cache_type == 0 || query_cache_size == 0)
1497 if (xa_state == XA_IDLE || xa_state == XA_PREPARED)
1500 if (!thd->lex->safe_to_cache_query)
1502 DBUG_PRINT(
"qcache", (
"SELECT is non-cacheable"));
1523 if ((my_toupper(system_charset_info, sql[i]) !=
'S' ||
1524 my_toupper(system_charset_info, sql[i + 1]) !=
'E' ||
1525 my_toupper(system_charset_info, sql[i + 2]) !=
'L') &&
1528 DBUG_PRINT(
"qcache", (
"The statement is not a SELECT; Not cached"));
1532 if (query_length > 20 && has_no_cache_directive(&sql[i+6]))
1538 DBUG_PRINT(
"qcache", (
"The statement has a SQL_NO_CACHE directive"));
1552 memcpy((
char *) &db_len, (sql + query_length + 1),
sizeof(
size_t));
1553 if (thd->db_length != db_len)
1560 DBUG_PRINT(
"qcache",
1561 (
"Current database has changed since start of query"));
1575 if (query_cache_size == 0)
1580 tot_length= query_length + 1 +
sizeof(size_t) +
1581 thd->db_length + QUERY_CACHE_FLAGS_SIZE;
1585 memcpy(sql + query_length + 1 +
sizeof(
size_t), thd->db, thd->db_length);
1586 DBUG_PRINT(
"qcache", (
"database: '%s' length: %u",
1587 thd->db, (
unsigned)thd->db_length));
1591 DBUG_PRINT(
"qcache", (
"No active database"));
1594 THD_STAGE_INFO(thd, stage_checking_query_cache_for_query);
1597 memset(&flags, 0, QUERY_CACHE_FLAGS_SIZE);
1598 flags.client_long_flag=
test(thd->client_capabilities & CLIENT_LONG_FLAG);
1599 flags.client_protocol_41=
test(thd->client_capabilities &
1600 CLIENT_PROTOCOL_41);
1601 flags.protocol_type= (
unsigned int) thd->protocol->type();
1602 flags.more_results_exists=
test(thd->server_status &
1603 SERVER_MORE_RESULTS_EXISTS);
1604 flags.in_trans= thd->in_active_multi_stmt_transaction();
1605 flags.autocommit=
test(thd->server_status & SERVER_STATUS_AUTOCOMMIT);
1606 flags.pkt_nr= thd->net.pkt_nr;
1607 flags.character_set_client_num= thd->variables.character_set_client->number;
1608 flags.character_set_results_num=
1609 (thd->variables.character_set_results ?
1610 thd->variables.character_set_results->number :
1612 flags.collation_connection_num= thd->variables.collation_connection->number;
1613 flags.limit= thd->variables.select_limit;
1614 flags.time_zone= thd->variables.time_zone;
1615 flags.sql_mode= thd->variables.sql_mode;
1616 flags.max_sort_length= thd->variables.max_sort_length;
1617 flags.group_concat_max_len= thd->variables.group_concat_max_len;
1618 flags.div_precision_increment= thd->variables.div_precincrement;
1619 flags.default_week_format= thd->variables.default_week_format;
1620 flags.lc_time_names= thd->variables.lc_time_names;
1621 DBUG_PRINT(
"qcache", (
"\
1622 long %d, 4.1: %d, bin_proto: %d, more results %d, pkt_nr: %d, \
1623 CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
1624 sql mode: 0x%llx, sort len: %lu, conncat len: %lu, div_precision: %lu, \
1625 def_week_frmt: %lu, in_trans: %d, autocommit: %d",
1626 (
int)flags.client_long_flag,
1627 (
int)flags.client_protocol_41,
1628 (
int)flags.protocol_type,
1629 (
int)flags.more_results_exists,
1631 flags.character_set_client_num,
1632 flags.character_set_results_num,
1633 flags.collation_connection_num,
1634 (ulong) flags.limit,
1635 (ulong) flags.time_zone,
1637 flags.max_sort_length,
1638 flags.group_concat_max_len,
1639 flags.div_precision_increment,
1640 flags.default_week_format,
1641 (
int)flags.in_trans,
1642 (
int)flags.autocommit));
1643 memcpy((uchar *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
1644 (uchar*) &flags, QUERY_CACHE_FLAGS_SIZE);
1648 if (query_block == 0 ||
1649 query_block->query()->result() == 0 ||
1650 query_block->query()->result()->type != Query_cache_block::RESULT)
1652 DBUG_PRINT(
"qcache", (
"No query in query hash or no results"));
1655 DBUG_PRINT(
"qcache", (
"Query in query hash 0x%lx", (ulong)query_block));
1658 BLOCK_LOCK_RD(query_block);
1660 query = query_block->query();
1661 result_block= query->result();
1662 #ifndef EMBEDDED_LIBRARY
1663 first_result_block= result_block;
1666 if (result_block == 0 || result_block->type != Query_cache_block::RESULT)
1669 DBUG_PRINT(
"qcache", (
"query found, but no data or data incomplete"));
1670 BLOCK_UNLOCK_RD(query_block);
1673 DBUG_PRINT(
"qcache", (
"Query have result 0x%lx", (ulong) query));
1675 if (thd->in_multi_stmt_transaction_mode() &&
1676 (query->tables_type() & HA_CACHE_TBL_TRANSACT))
1678 DBUG_PRINT(
"qcache",
1679 (
"we are in transaction and have transaction tables in query"));
1680 BLOCK_UNLOCK_RD(query_block);
1685 THD_STAGE_INFO(thd, stage_checking_privileges_on_cached_query);
1686 block_table= query_block->table(0);
1687 block_table_end= block_table+query_block->n_tables;
1688 for (; block_table != block_table_end; block_table++)
1700 for (tmptable= thd->temporary_tables; tmptable ; tmptable= tmptable->next)
1702 if (tmptable->s->table_cache_key.length - TMP_TABLE_KEY_EXTRA ==
1703 table->key_length() &&
1704 !memcmp(tmptable->s->table_cache_key.str, table->data(),
1705 table->key_length()))
1707 DBUG_PRINT(
"qcache",
1708 (
"Temporary table detected: '%s.%s'",
1709 table_list.db, table_list.alias));
1716 thd->lex->safe_to_cache_query=0;
1717 BLOCK_UNLOCK_RD(query_block);
1722 memset(&table_list, 0,
sizeof(table_list));
1723 table_list.db = table->db();
1724 table_list.alias= table_list.table_name= table->table();
1725 #ifndef NO_EMBEDDED_ACCESS_CHECKS
1728 DBUG_PRINT(
"qcache",
1729 (
"probably no SELECT access to %s.%s => return to normal processing",
1730 table_list.db, table_list.alias));
1732 thd->lex->safe_to_cache_query=0;
1733 BLOCK_UNLOCK_RD(query_block);
1738 DBUG_PRINT(
"qcache", (
"Need to check column privileges for %s.%s",
1739 table_list.db, table_list.alias));
1740 BLOCK_UNLOCK_RD(query_block);
1741 thd->lex->safe_to_cache_query= 0;
1745 engine_data= table->engine_data();
1746 if (table->callback())
1748 char qcache_se_key_name[FN_REFLEN + 1];
1749 uint qcache_se_key_len;
1750 engine_data= table->engine_data();
1752 qcache_se_key_len= build_table_filename(qcache_se_key_name,
1753 sizeof(qcache_se_key_name),
1754 table->db(), table->table(),
1755 "", SKIP_SYMDIR_ACCESS);
1757 if (!(*table->callback())(thd, qcache_se_key_name,
1758 qcache_se_key_len, &engine_data))
1760 DBUG_PRINT(
"qcache", (
"Handler does not allow caching for %s.%s",
1761 table_list.db, table_list.alias));
1762 BLOCK_UNLOCK_RD(query_block);
1763 if (engine_data != table->engine_data())
1765 DBUG_PRINT(
"qcache",
1766 (
"Handler require invalidation queries of %s.%s %lu-%lu",
1767 table_list.db, table_list.alias,
1768 (ulong) engine_data, (ulong) table->engine_data()));
1769 invalidate_table_internal(thd, (uchar *) table->db(),
1770 table->key_length());
1773 thd->lex->safe_to_cache_query= 0;
1779 DBUG_ASSERT(! thd->transaction_rollback_request);
1780 trans_rollback_stmt(thd);
1785 DBUG_PRINT(
"qcache", (
"handler allow caching %s,%s",
1786 table_list.db, table_list.alias));
1788 move_to_query_list_end(query_block);
1795 #ifndef EMBEDDED_LIBRARY
1796 THD_STAGE_INFO(thd, stage_sending_cached_result_to_client);
1799 DBUG_PRINT(
"qcache", (
"Results (len: %lu used: %lu headers: %lu)",
1800 result_block->length, result_block->used,
1801 (ulong) (result_block->headers_len()+
1805 if (send_data_in_chunks(&thd->net, result->data(),
1806 result_block->used -
1807 result_block->headers_len() -
1810 result_block = result_block->next;
1811 thd->net.pkt_nr= query->last_pkt_nr;
1812 }
while (result_block != first_result_block);
1817 emb_load_querycache_result(thd, &qs);
1821 thd->limit_found_rows = query->found_rows();
1822 thd->status_var.last_query_cost= 0.0;
1826 thd->query(), thd->query_length(), NULL,
1827 thd->variables.character_set_client);
1830 .add(
"query_result_read_from_cache",
true);
1839 (void) trans_commit_stmt(thd);
1840 if (!thd->get_stmt_da()->is_set())
1841 thd->get_stmt_da()->disable_status();
1843 BLOCK_UNLOCK_RD(query_block);
1844 MYSQL_QUERY_CACHE_HIT(thd->query(), (ulong) thd->limit_found_rows);
1850 MYSQL_QUERY_CACHE_MISS(thd->query());
1859 void Query_cache::invalidate(THD *thd,
TABLE_LIST *tables_used,
1860 my_bool using_transactions)
1862 DBUG_ENTER(
"Query_cache::invalidate (table list)");
1866 using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
1867 for (; tables_used; tables_used= tables_used->next_local)
1869 DBUG_ASSERT(!using_transactions || tables_used->table!=0);
1872 if (using_transactions &&
1874 HA_CACHE_TBL_TRANSACT))
1880 thd->add_changed_table(tables_used->table);
1882 invalidate_table(thd, tables_used);
1885 DEBUG_SYNC(thd,
"wait_after_query_cache_invalidate");
1892 DBUG_ENTER(
"Query_cache::invalidate (changed table list)");
1896 THD *thd= current_thd;
1897 for (; tables_used; tables_used= tables_used->next)
1899 THD_STAGE_INFO(thd, stage_invalidating_query_cache_entries_table_list);
1900 invalidate_table(thd, (uchar*) tables_used->key, tables_used->key_length);
1901 DBUG_PRINT(
"qcache", (
"db: %s table: %s", tables_used->key,
1903 strlen(tables_used->key)+1));
1919 void Query_cache::invalidate_locked_for_write(
TABLE_LIST *tables_used)
1921 DBUG_ENTER(
"Query_cache::invalidate_locked_for_write");
1925 THD *thd= current_thd;
1926 for (; tables_used; tables_used= tables_used->next_local)
1928 THD_STAGE_INFO(thd, stage_invalidating_query_cache_entries_table);
1929 if (tables_used->lock_type >= TL_WRITE_ALLOW_WRITE &&
1932 invalidate_table(thd, tables_used->table);
1942 void Query_cache::invalidate(THD *thd,
TABLE *table,
1943 my_bool using_transactions)
1945 DBUG_ENTER(
"Query_cache::invalidate (table)");
1949 using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
1950 if (using_transactions &&
1952 thd->add_changed_table(table);
1954 invalidate_table(thd, table);
1960 void Query_cache::invalidate(THD *thd,
const char *key, uint32 key_length,
1961 my_bool using_transactions)
1963 DBUG_ENTER(
"Query_cache::invalidate (key)");
1967 using_transactions= using_transactions && thd->in_multi_stmt_transaction_mode();
1968 if (using_transactions)
1969 thd->add_changed_table(key, key_length);
1971 invalidate_table(thd, (uchar*)key, key_length);
1981 void Query_cache::invalidate(
char *db)
1984 DBUG_ENTER(
"Query_cache::invalidate (db)");
1988 bool restart= FALSE;
1995 THD *thd= current_thd;
1997 if (query_cache_size > 0)
2008 if (strcmp(table->db(),db) == 0)
2011 invalidate_query_block_list(thd,list_root);
2021 if (tables_blocks == 0)
2023 table_block= tables_blocks;
2029 else if (table_block->type == Query_cache_block::FREE)
2032 table_block= tables_blocks;
2038 }
while (table_block != tables_blocks);
2055 void Query_cache::invalidate_by_MyISAM_filename(
const char *filename)
2057 DBUG_ENTER(
"Query_cache::invalidate_by_MyISAM_filename");
2060 char key[MAX_DBKEY_LENGTH];
2062 uint key_length= filename_2_table_key(key, filename, &db_length);
2063 THD *thd= current_thd;
2064 invalidate_table(thd,(uchar *)key, key_length);
2070 void Query_cache::flush()
2072 DBUG_ENTER(
"Query_cache::flush");
2076 QC_DEBUG_SYNC(
"wait_in_query_cache_flush1");
2079 if (query_cache_size > 0)
2086 DBUG_EXECUTE(
"check_querycache",query_cache.check_integrity(1););
2102 void Query_cache::pack(ulong join_limit, uint iteration_limit)
2104 DBUG_ENTER(
"Query_cache::pack");
2116 if (query_cache_size == 0)
2126 }
while ((++i < iteration_limit) && join_results(join_limit));
2133 void Query_cache::destroy()
2135 DBUG_ENTER(
"Query_cache::destroy");
2138 DBUG_PRINT(
"qcache", (
"Query Cache not initialized"));
2159 void Query_cache::init()
2161 DBUG_ENTER(
"Query_cache::init");
2163 &structure_guard_mutex, MY_MUTEX_INIT_FAST);
2165 &COND_cache_status_changed, NULL);
2166 m_cache_lock_status= Query_cache::UNLOCKED;
2174 if (global_system_variables.query_cache_type == 0)
2175 query_cache.disable_query_cache();
2181 ulong Query_cache::init_cache()
2183 uint mem_bin_count, num, step;
2184 ulong mem_bin_size, prev_size, inc;
2185 ulong additional_data_size, max_mem_bin_size, approx_additional_data_size;
2188 DBUG_ENTER(
"Query_cache::init_cache");
2190 approx_additional_data_size = (
sizeof(
Query_cache) +
2191 sizeof(uchar*)*(def_query_hash_size+
2192 def_table_hash_size));
2193 if (query_cache_size < approx_additional_data_size)
2196 query_cache_size-= approx_additional_data_size;
2197 align= query_cache_size % ALIGN_SIZE(1);
2200 query_cache_size-= align;
2201 approx_additional_data_size+= align;
2209 max_mem_bin_size = query_cache_size >> QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2;
2210 mem_bin_count = (uint) ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
2211 QUERY_CACHE_MEM_BIN_PARTS_MUL);
2214 mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
2216 if (mem_bin_size <= min_allocation_unit)
2218 DBUG_PRINT(
"qcache", (
"too small query cache => query cache disabled"));
2222 while (mem_bin_size > min_allocation_unit)
2224 mem_bin_num += mem_bin_count;
2225 prev_size = mem_bin_size;
2226 mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
2228 mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
2229 mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
2232 if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
2233 mem_bin_count= (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
2235 inc = (prev_size - mem_bin_size) / mem_bin_count;
2236 mem_bin_num += (mem_bin_count - (min_allocation_unit - mem_bin_size)/inc);
2238 additional_data_size = ((mem_bin_num+1) *
2243 if (query_cache_size < additional_data_size)
2245 query_cache_size -= additional_data_size;
2247 if (!(cache= (uchar *)
2248 my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
2251 DBUG_PRINT(
"qcache", (
"cache length %lu, min unit %lu, %u bins",
2252 query_cache_size, min_allocation_unit, mem_bin_num));
2256 (cache + mem_bin_steps *
2260 first_block->init(query_cache_size);
2262 first_block->pnext=first_block->pprev=first_block;
2263 first_block->next=first_block->prev=first_block;
2267 bins[0].init(max_mem_bin_size);
2268 steps[0].init(max_mem_bin_size,0,0);
2269 mem_bin_count = (uint) ((1 + QUERY_CACHE_MEM_BIN_PARTS_INC) *
2270 QUERY_CACHE_MEM_BIN_PARTS_MUL);
2272 mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
2273 while (mem_bin_size > min_allocation_unit)
2275 ulong incr = (steps[step-1].size - mem_bin_size) / mem_bin_count;
2276 unsigned long size = mem_bin_size;
2277 for (uint i= mem_bin_count; i > 0; i--)
2279 bins[num+i-1].init(size);
2282 num += mem_bin_count;
2283 steps[step].init(mem_bin_size, num-1, incr);
2284 mem_bin_size >>= QUERY_CACHE_MEM_BIN_STEP_PWR2;
2286 mem_bin_count += QUERY_CACHE_MEM_BIN_PARTS_INC;
2287 mem_bin_count = (uint) (mem_bin_count * QUERY_CACHE_MEM_BIN_PARTS_MUL);
2288 if (mem_bin_count > (mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2))
2289 mem_bin_count=(mem_bin_size >> QUERY_CACHE_MEM_BIN_SPC_LIM_PWR2);
2291 inc = (steps[step-1].size - mem_bin_size) / mem_bin_count;
2298 steps[step].init(mem_bin_size, num + mem_bin_count - 1, inc);
2300 uint skiped = (min_allocation_unit - mem_bin_size)/inc;
2301 ulong size = mem_bin_size + inc*skiped;
2302 uint i = mem_bin_count - skiped;
2305 bins[num+
i].init(size);
2309 bins[mem_bin_num].number = 1;
2310 free_memory = free_memory_blocks = 0;
2311 insert_into_free_memory_list(first_block);
2315 (void) my_hash_init(&queries, &my_charset_bin, def_query_hash_size, 0, 0,
2316 query_cache_query_get_key, 0, 0);
2317 #ifndef FN_NO_CASE_SENSE
2326 (void) my_hash_init(&tables, &my_charset_bin, def_table_hash_size, 0, 0,
2327 query_cache_table_get_key, 0, 0);
2337 (void) my_hash_init(&tables,
2338 lower_case_table_names ? &my_charset_bin :
2340 def_table_hash_size, 0, 0,query_cache_table_get_key,
2344 queries_in_cache = 0;
2346 DBUG_RETURN(query_cache_size +
2347 additional_data_size + approx_additional_data_size);
2357 void Query_cache::make_disabled()
2359 DBUG_ENTER(
"Query_cache::make_disabled");
2360 query_cache_size= 0;
2363 free_memory_blocks= 0;
2367 mem_bin_num= mem_bin_steps= 0;
2368 queries_in_cache= 0;
2385 void Query_cache::free_cache()
2387 DBUG_ENTER(
"Query_cache::free_cache");
2391 my_hash_free(&queries);
2392 my_hash_free(&tables);
2414 void Query_cache::flush_cache()
2416 QC_DEBUG_SYNC(
"wait_in_query_cache_flush2");
2418 my_hash_reset(&queries);
2419 while (queries_blocks != 0)
2421 BLOCK_LOCK_WR(queries_blocks);
2422 free_query_internal(queries_blocks);
2431 my_bool Query_cache::free_old_query()
2433 DBUG_ENTER(
"Query_cache::free_old_query");
2442 if (queries_blocks != 0)
2449 if (header->result() != 0 &&
2450 header->result()->type == Query_cache_block::RESULT &&
2451 block->query()->try_lock_writing())
2453 query_block =
block;
2456 }
while ((block=block->next) != queries_blocks );
2459 if (query_block != 0)
2461 free_query(query_block);
2490 DBUG_ENTER(
"Query_cache::free_query_internal");
2491 DBUG_PRINT(
"qcache", (
"free query 0x%lx %lu bytes result",
2492 (ulong) query_block,
2493 query_block->query()->length() ));
2499 if (query->writer() != 0)
2502 query->writer()->first_query_block= NULL;
2505 double_linked_list_exclude(query_block, &queries_blocks);
2508 for (TABLE_COUNTER_TYPE i= 0; i < query_block->n_tables; i++)
2509 unlink_table(table++);
2516 if (result_block != 0)
2518 if (result_block->type != Query_cache_block::RESULT)
2529 free_memory_block(current);
2530 }
while (block != result_block);
2539 query->unlock_n_destroy();
2540 free_memory_block(query_block);
2560 DBUG_ENTER(
"Query_cache::free_query");
2561 DBUG_PRINT(
"qcache", (
"free query 0x%lx %lu bytes result",
2562 (ulong) query_block,
2563 query_block->query()->length() ));
2565 my_hash_delete(&queries,(uchar *) query_block);
2566 free_query_internal(query_block);
2576 Query_cache::write_block_data(ulong data_len, uchar* data,
2578 Query_cache_block::block_type
type,
2579 TABLE_COUNTER_TYPE ntab)
2584 ulong len = data_len + all_headers_len;
2585 ulong align_len= ALIGN_SIZE(len);
2586 DBUG_ENTER(
"Query_cache::write_block_data");
2587 DBUG_PRINT(
"qcache", (
"data: %ld, header: %ld, all header: %ld",
2588 data_len, header_len, all_headers_len));
2590 min_allocation_unit),1, 0);
2594 block->n_tables = ntab;
2597 memcpy((uchar *) block+ all_headers_len, data, data_len);
2605 ulong data_len, uchar* data,
2608 DBUG_ENTER(
"Query_cache::append_result_data");
2609 DBUG_PRINT(
"qcache", (
"append %lu bytes to 0x%lx query",
2610 data_len, (
long) query_block));
2612 if (query_block->query()->add(data_len) > query_cache_limit)
2614 DBUG_PRINT(
"qcache", (
"size limit reached %lu > %lu",
2615 query_block->query()->length(),
2616 query_cache_limit));
2619 if (*current_block == 0)
2621 DBUG_PRINT(
"qcache", (
"allocated first result data block %lu", data_len));
2622 DBUG_RETURN(write_result_data(current_block, data_len, data, query_block,
2623 Query_cache_block::RES_BEG));
2627 DBUG_PRINT(
"qcache", (
"lastblock 0x%lx len %lu used %lu",
2628 (ulong) last_block, last_block->length,
2630 my_bool success = 1;
2631 ulong last_block_free_space= last_block->length - last_block->used;
2640 ulong tail = data_len - last_block_free_space;
2641 ulong append_min = get_min_append_result_data_size();
2642 if (last_block_free_space < data_len &&
2643 append_next_free_block(last_block,
2644 max(tail, append_min)))
2645 last_block_free_space = last_block->length - last_block->used;
2647 if (last_block_free_space < data_len)
2649 DBUG_PRINT(
"qcache", (
"allocate new block for %lu bytes",
2650 data_len-last_block_free_space));
2652 success = write_result_data(&new_block, data_len-last_block_free_space,
2653 (uchar*)(((uchar*)data)+last_block_free_space),
2655 Query_cache_block::RES_CONT);
2661 double_linked_list_join(last_block, new_block);
2670 if (success && last_block_free_space > 0)
2672 ulong to_copy = min(data_len,last_block_free_space);
2673 DBUG_PRINT(
"qcache", (
"use free space %lub at block 0x%lx to copy %lub",
2674 last_block_free_space, (ulong)last_block, to_copy));
2675 memcpy((uchar*) last_block + last_block->used, data, to_copy);
2676 last_block->used+=to_copy;
2678 DBUG_RETURN(success);
2683 ulong data_len, uchar* data,
2685 Query_cache_block::block_type type)
2687 DBUG_ENTER(
"Query_cache::write_result_data");
2688 DBUG_PRINT(
"qcache", (
"data_len %lu",data_len));
2699 my_bool success = allocate_data_chain(result_block, data_len, query_block,
2700 type == Query_cache_block::RES_BEG);
2707 #ifndef EMBEDDED_LIBRARY
2714 ulong length = block->used - headers_len;
2715 DBUG_PRINT(
"qcache", (
"write %lu byte in block 0x%lx",length,
2717 memcpy((uchar*) block+headers_len, rest, length);
2719 block = block->next;
2720 type = Query_cache_block::RES_CONT;
2721 }
while (block != *result_block);
2727 (*result_block)->type=
type;
2729 emb_store_querycache_result(&qs, (THD*)data);
2734 if (*result_block != 0)
2741 block = block->next;
2742 free_memory_block(current);
2743 }
while (block != *result_block);
2751 DBUG_PRINT(
"qcache", (
"success %d", (
int) success));
2752 DBUG_RETURN(success);
2755 inline ulong Query_cache::get_min_first_result_data_size()
2757 if (queries_in_cache < QUERY_CACHE_MIN_ESTIMATED_QUERIES_NUMBER)
2758 return min_result_data_size;
2759 ulong avg_result = (query_cache_size - free_memory) / queries_in_cache;
2760 avg_result = min(avg_result, query_cache_limit);
2761 return max(min_result_data_size, avg_result);
2764 inline ulong Query_cache::get_min_append_result_data_size()
2766 return min_result_data_size;
2775 my_bool first_block_arg)
2779 ulong min_size = (first_block_arg ?
2780 get_min_first_result_data_size():
2781 get_min_append_result_data_size());
2784 DBUG_ENTER(
"Query_cache::allocate_data_chain");
2785 DBUG_PRINT(
"qcache", (
"data_len %lu, all_headers_len %lu",
2786 data_len, all_headers_len));
2790 ulong len= data_len + all_headers_len;
2791 ulong align_len= ALIGN_SIZE(len);
2793 if (!(new_block= allocate_block(max(min_size, align_len),
2794 min_result_data_size == 0,
2795 all_headers_len + min_result_data_size)))
2797 DBUG_PRINT(
"warning", (
"Can't allocate block for results"));
2801 new_block->n_tables = 0;
2802 new_block->used = min(len, new_block->length);
2803 new_block->type = Query_cache_block::RES_INCOMPLETE;
2804 new_block->next = new_block->prev = new_block;
2806 header->parent(query_block);
2808 DBUG_PRINT(
"qcache", (
"Block len %lu used %lu",
2809 new_block->length, new_block->used));
2812 double_linked_list_join(prev_block, new_block);
2814 *result_block= new_block;
2815 if (new_block->length >= len)
2822 data_len= len - new_block->length;
2823 prev_block= new_block;
2837 void Query_cache::invalidate_table(THD *thd,
TABLE_LIST *table_list)
2839 if (table_list->table != 0)
2840 invalidate_table(thd, table_list->table);
2848 invalidate_table(thd, (uchar *)key, key_length);
2852 void Query_cache::invalidate_table(THD *thd,
TABLE *table)
2854 invalidate_table(thd, (uchar*) table->s->table_cache_key.str,
2855 table->s->table_cache_key.length);
2858 void Query_cache::invalidate_table(THD *thd, uchar * key, uint32 key_length)
2860 DEBUG_SYNC(thd,
"wait_in_query_cache_invalidate1");
2868 DEBUG_SYNC(thd,
"wait_in_query_cache_invalidate2");
2870 if (query_cache_size > 0)
2871 invalidate_table_internal(thd, key, key_length);
2886 Query_cache::invalidate_table_internal(THD *thd, uchar *key, uint32 key_length)
2893 invalidate_query_block_list(thd, list_root);
2910 Query_cache::invalidate_query_block_list(THD *thd,
2913 while (list_root->
next != list_root)
2916 BLOCK_LOCK_WR(query_block);
2917 free_query(query_block);
2937 Query_cache::register_tables_from_list(
TABLE_LIST *tables_used,
2938 TABLE_COUNTER_TYPE counter,
2941 TABLE_COUNTER_TYPE
n;
2942 DBUG_ENTER(
"Query_cache::register_tables_from_list");
2945 tables_used= tables_used->next_global, n++, block_table++)
2949 DBUG_PRINT(
"qcache", (
"derived table skipped"));
2955 if (tables_used->view)
2959 DBUG_PRINT(
"qcache", (
"view: %s db: %s",
2960 tables_used->view_name.str,
2961 tables_used->view_db.str));
2966 if (!insert_table(key_length, key, block_table,
2967 tables_used->view_db.length + 1,
2968 HA_CACHE_TBL_NONTRANSACT, 0, 0))
2977 DBUG_PRINT(
"qcache",
2978 (
"table: %s db: %s openinfo: 0x%lx keylen: %lu key: 0x%lx",
2979 tables_used->table->s->table_name.str,
2980 tables_used->table->s->table_cache_key.str,
2981 (ulong) tables_used->table,
2982 (ulong) tables_used->table->s->table_cache_key.length,
2983 (ulong) tables_used->table->s->table_cache_key.str));
2985 if (!insert_table(tables_used->table->s->table_cache_key.length,
2986 tables_used->table->s->table_cache_key.str,
2988 tables_used->db_length,
2990 tables_used->callback_func,
2991 tables_used->engine_data))
2994 #ifdef WITH_MYISAMMRG_STORAGE_ENGINE
2999 if (tables_used->table->s->db_type()->db_type == DB_TYPE_MRG_MYISAM)
3004 table != file->end_table ;
3007 char key[MAX_DBKEY_LENGTH];
3009 uint key_length= filename_2_table_key(key, table->table->filename,
3011 (++block_table)->n= ++n;
3015 if (!insert_table(key_length, key, block_table,
3025 DBUG_RETURN(n - counter);
3040 TABLE_COUNTER_TYPE tables_arg)
3042 TABLE_COUNTER_TYPE
n;
3043 DBUG_PRINT(
"qcache", (
"register tables block 0x%lx, n %d, header %x",
3044 (ulong) block, (
int) tables_arg,
3049 n= register_tables_from_list(tables_used, 0, block_table);
3072 Query_cache::insert_table(uint key_len,
const char *key,
3074 uint32 db_length, uint8 cache_type,
3075 qc_engine_callback callback,
3076 ulonglong engine_data)
3078 DBUG_ENTER(
"Query_cache::insert_table");
3079 DBUG_PRINT(
"qcache", (
"insert table node 0x%lx, len %d",
3080 (ulong)node, key_len));
3082 THD *thd= current_thd;
3088 table_block->table()->engine_data() != engine_data)
3090 DBUG_PRINT(
"qcache",
3091 (
"Handler require invalidation queries of %s.%s %lu-%lu",
3092 table_block->table()->db(),
3093 table_block->table()->table(),
3094 (ulong) engine_data,
3095 (ulong) table_block->table()->engine_data()));
3102 invalidate_query_block_list(thd, list_root);
3108 if (table_block == 0)
3110 DBUG_PRINT(
"qcache", (
"new table block from 0x%lx (%u)",
3111 (ulong) key, (
int) key_len));
3112 table_block= write_block_data(key_len, (uchar*) key,
3114 Query_cache_block::TABLE, 1);
3115 if (table_block == 0)
3117 DBUG_PRINT(
"qcache", (
"Can't write table name to cache"));
3121 double_linked_list_simple_include(table_block,
3133 list_root->
next= list_root->prev= list_root;
3135 if (my_hash_insert(&tables, (
const uchar *) table_block))
3137 DBUG_PRINT(
"qcache", (
"Can't insert table to hash"));
3139 free_memory_block(table_block);
3142 char *db= header->db();
3143 header->table(db + db_length + 1);
3144 header->key_length(key_len);
3145 header->type(cache_type);
3146 header->callback(callback);
3147 header->engine_data(engine_data);
3163 list_root->
next= node;
3164 node->
next->prev= node;
3165 node->prev= list_root;
3166 node->
parent= table_block->table();
3179 DBUG_ENTER(
"Query_cache::unlink_table");
3181 node->
next->prev= node->prev;
3188 if (neighbour->
next == neighbour)
3199 double_linked_list_exclude(table_block,
3201 my_hash_delete(&tables,(uchar *) table_block);
3202 free_memory_block(table_block);
3212 Query_cache::allocate_block(ulong len, my_bool not_less, ulong minimum)
3214 DBUG_ENTER(
"Query_cache::allocate_block");
3215 DBUG_PRINT(
"qcache", (
"len %lu, not less %d, min %lu",
3216 len, not_less, minimum));
3218 if (len >= min(query_cache_size, query_cache_limit))
3220 DBUG_PRINT(
"qcache", (
"Query cache hase only %lu memory and limit %lu",
3221 query_cache_size, query_cache_limit));
3229 block= get_free_block(len, not_less, minimum);
3231 while (block == 0 && !free_old_query());
3235 if (block->length >= ALIGN_SIZE(len) + min_allocation_unit)
3236 split_block(block,ALIGN_SIZE(len));
3244 Query_cache::get_free_block(ulong len, my_bool not_less, ulong min)
3247 DBUG_ENTER(
"Query_cache::get_free_block");
3248 DBUG_PRINT(
"qcache",(
"length %lu, not_less %d, min %lu", len,
3249 (
int)not_less, min));
3252 uint start = find_bin(len);
3254 if (bins[start].number != 0)
3257 if (list->prev->length >= len)
3261 while ( n < QUERY_CACHE_MEM_BIN_TRY &&
3262 first->length < len)
3267 if (first->length >= len)
3273 while (n < QUERY_CACHE_MEM_BIN_TRY &&
3274 block->length > len)
3279 if (block->length < len)
3286 if (block == 0 && start > 0)
3288 DBUG_PRINT(
"qcache",(
"Try bins with bigger block size"));
3291 while (i > 0 && bins[i].number == 0)
3293 if (bins[i].number > 0)
3294 block = bins[
i].free_blocks;
3298 if (block == 0 && ! not_less)
3300 DBUG_PRINT(
"qcache",(
"Try to allocate a smaller block"));
3301 if (first != 0 && first->length > min)
3307 for (i= start+1 ; bins[
i].number == 0 ; i++) ;
3308 if (i < mem_bin_num && bins[i].free_blocks->prev->length >= min)
3309 block = bins[
i].free_blocks->prev;
3313 exclude_from_free_memory_list(block);
3315 DBUG_PRINT(
"qcache",(
"getting block 0x%lx", (ulong) block));
3322 DBUG_ENTER(
"Query_cache::free_memory_block");
3324 block->type= Query_cache_block::FREE;
3325 DBUG_PRINT(
"qcache",
3326 (
"first_block 0x%lx, block 0x%lx, pnext 0x%lx pprev 0x%lx",
3327 (ulong) first_block, (ulong) block, (ulong) block->pnext,
3328 (ulong) block->pprev));
3330 if (block->pnext != first_block && block->pnext->is_free())
3331 block = join_free_blocks(block, block->pnext);
3332 if (block != first_block && block->pprev->is_free())
3333 block = join_free_blocks(block->pprev, block->pprev);
3334 insert_into_free_memory_list(block);
3341 DBUG_ENTER(
"Query_cache::split_block");
3344 new_block->init(block->length - len);
3347 new_block->pnext = block->pnext;
3348 block->pnext = new_block;
3349 new_block->pprev =
block;
3350 new_block->pnext->pprev = new_block;
3352 if (block->type == Query_cache_block::FREE)
3355 insert_into_free_memory_list(new_block);
3358 free_memory_block(new_block);
3360 DBUG_PRINT(
"qcache", (
"split 0x%lx (%lu) new 0x%lx",
3361 (ulong) block, len, (ulong) new_block));
3371 DBUG_ENTER(
"Query_cache::join_free_blocks");
3372 DBUG_PRINT(
"qcache",
3373 (
"join first 0x%lx, pnext 0x%lx, in list 0x%lx",
3374 (ulong) first_block_arg, (ulong) first_block_arg->pnext,
3375 (ulong) block_in_list));
3377 exclude_from_free_memory_list(block_in_list);
3378 second_block = first_block_arg->pnext;
3380 second_block->used=0;
3381 second_block->destroy();
3384 first_block_arg->length += second_block->length;
3385 first_block_arg->pnext = second_block->pnext;
3386 second_block->pnext->pprev = first_block_arg;
3388 DBUG_RETURN(first_block_arg);
3396 DBUG_ENTER(
"Query_cache::append_next_free_block");
3397 DBUG_PRINT(
"enter", (
"block 0x%lx, add_size %lu", (ulong) block,
3400 if (next_block != first_block && next_block->is_free())
3402 ulong old_len = block->length;
3403 exclude_from_free_memory_list(next_block);
3404 next_block->destroy();
3407 block->length += next_block->length;
3408 block->pnext = next_block->pnext;
3409 next_block->pnext->pprev =
block;
3411 if (block->length > ALIGN_SIZE(old_len + add_size) + min_allocation_unit)
3412 split_block(block,ALIGN_SIZE(old_len + add_size));
3413 DBUG_PRINT(
"exit", (
"block was appended"));
3422 DBUG_ENTER(
"Query_cache::exclude_from_free_memory_list");
3424 free_block->data());
3425 double_linked_list_exclude(free_block, &bin->free_blocks);
3427 free_memory-=free_block->length;
3428 free_memory_blocks--;
3429 DBUG_PRINT(
"qcache",(
"exclude block 0x%lx, bin 0x%lx", (ulong) free_block,
3436 DBUG_ENTER(
"Query_cache::insert_into_free_memory_list");
3437 uint idx = find_bin(free_block->length);
3438 insert_into_free_memory_sorted_list(free_block, &bins[idx].free_blocks);
3444 free_block->data());
3445 *bin_ptr = bins+idx;
3446 (*bin_ptr)->number++;
3447 DBUG_PRINT(
"qcache",(
"insert block 0x%lx, bin[%d] 0x%lx",
3448 (ulong) free_block, idx, (ulong) *bin_ptr));
3452 uint Query_cache::find_bin(ulong size)
3454 DBUG_ENTER(
"Query_cache::find_bin");
3456 int left = 0, right = mem_bin_steps;
3459 int middle = (left + right) / 2;
3460 if (steps[middle].size > size)
3464 }
while (left < right);
3468 DBUG_PRINT(
"qcache", (
"first bin (# 0), size %lu",size));
3471 uint bin = steps[left].idx -
3472 (uint)((size - steps[left].size)/steps[left].increment);
3474 DBUG_PRINT(
"qcache", (
"bin %u step %u, size %lu step size %lu",
3475 bin, left, size, steps[left].size));
3486 DBUG_ENTER(
"Query_cache::move_to_query_list_end");
3487 double_linked_list_exclude(query_block, &queries_blocks);
3488 double_linked_list_simple_include(query_block, &queries_blocks);
3498 DBUG_ENTER(
"Query_cache::insert_into_free_memory_sorted_list");
3504 new_block->used = 0;
3505 new_block->n_tables = 0;
3506 new_block->type = Query_cache_block::FREE;
3510 *list = new_block->next=new_block->prev=new_block;
3511 DBUG_PRINT(
"qcache", (
"inserted into empty list"));
3516 if (point->length >= new_block->length)
3518 point = point->prev;
3524 while (point->next != *list &&
3525 point->next->length < new_block->length)
3528 new_block->prev = point;
3529 new_block->next = point->next;
3530 new_block->next->prev = new_block;
3531 point->next = new_block;
3533 free_memory+=new_block->length;
3534 free_memory_blocks++;
3544 DBUG_ENTER(
"Query_cache::double_linked_list_simple_include");
3545 DBUG_PRINT(
"qcache", (
"including block 0x%lx", (ulong) point));
3546 if (*list_pointer == 0)
3547 *list_pointer=point->next=point->prev=point;
3551 point->next = (*list_pointer);
3552 point->prev = (*list_pointer)->prev;
3553 point->prev->next = point;
3554 (*list_pointer)->prev = point;
3563 DBUG_ENTER(
"Query_cache::double_linked_list_exclude");
3564 DBUG_PRINT(
"qcache", (
"excluding block 0x%lx, list 0x%lx",
3565 (ulong) point, (ulong) list_pointer));
3566 if (point->next == point)
3570 point->next->prev = point->prev;
3571 point->prev->next = point->next;
3575 if (point == *list_pointer)
3576 *list_pointer= point->next;
3586 *tail_tail = tail_head->prev;
3587 head_head->prev = tail_tail;
3588 head_tail->next = tail_head;
3589 tail_head->prev = head_tail;
3590 tail_tail->next = head_head;
3612 Query_cache::process_and_count_tables(THD *thd,
TABLE_LIST *tables_used,
3615 DBUG_ENTER(
"process_and_count_tables");
3616 TABLE_COUNTER_TYPE table_count = 0;
3617 for (; tables_used; tables_used= tables_used->next_global)
3620 #ifndef NO_EMBEDDED_ACCESS_CHECKS
3639 tables_used->belong_to_view == NULL)
3641 DBUG_PRINT(
"qcache", (
"Don't cache statement as it refers to "
3642 "tables with column privileges."));
3643 thd->lex->safe_to_cache_query= 0;
3647 if (tables_used->view)
3649 DBUG_PRINT(
"qcache", (
"view: %s db: %s",
3650 tables_used->view_name.str,
3651 tables_used->view_db.str));
3652 *tables_type|= HA_CACHE_TBL_NONTRANSACT;
3656 DBUG_PRINT(
"qcache", (
"table: %s db: %s type: %u",
3657 tables_used->table->s->table_name.str,
3658 tables_used->table->s->db.str,
3659 tables_used->table->s->db_type()->db_type));
3663 DBUG_PRINT(
"qcache", (
"derived table skipped"));
3672 if (tables_used->table->s->tmp_table != NO_TMP_TABLE ||
3673 (*tables_type & HA_CACHE_TBL_NOCACHE) ||
3674 (tables_used->db_length == 5 &&
3675 my_strnncoll(table_alias_charset,
3676 (uchar*)tables_used->table->s->table_cache_key.str, 6,
3677 (uchar*)
"mysql",6) == 0))
3679 DBUG_PRINT(
"qcache",
3680 (
"select not cacheable: temporary, system or "
3681 "other non-cacheable table(s)"));
3684 #ifdef WITH_MYISAMMRG_STORAGE_ENGINE
3689 if (tables_used->table->s->db_type()->db_type == DB_TYPE_MRG_MYISAM)
3693 table_count+= (file->end_table - file->open_tables);
3698 DBUG_RETURN(table_count);
3708 Query_cache::is_cacheable(THD *thd,
size_t query_len,
const char *query,
3712 TABLE_COUNTER_TYPE table_count;
3713 DBUG_ENTER(
"Query_cache::is_cacheable");
3715 if (query_cache_is_cacheable_query(lex) &&
3716 (thd->variables.query_cache_type == 1 ||
3717 (thd->variables.query_cache_type == 2 && (lex->select_lex.options &
3718 OPTION_TO_QUERY_CACHE))))
3720 DBUG_PRINT(
"qcache", (
"options: %lx %lx type: %u",
3721 (
long) OPTION_TO_QUERY_CACHE,
3722 (
long) lex->select_lex.options,
3723 (
int) thd->variables.query_cache_type));
3725 if (!(table_count= process_and_count_tables(thd, tables_used,
3729 if (thd->in_multi_stmt_transaction_mode() &&
3730 ((*tables_type)&HA_CACHE_TBL_TRANSACT))
3732 DBUG_PRINT(
"qcache", (
"not in autocommin mode"));
3735 DBUG_PRINT(
"qcache", (
"select is using %d tables", table_count));
3736 DBUG_RETURN(table_count);
3739 DBUG_PRINT(
"qcache",
3740 (
"not interesting query: %d or not cacheable, options %lx %lx type: %u",
3741 (
int) lex->sql_command,
3742 (
long) OPTION_TO_QUERY_CACHE,
3743 (
long) lex->select_lex.options,
3744 (
int) thd->variables.query_cache_type));
3760 my_bool Query_cache::ask_handler_allowance(THD *thd,
3763 DBUG_ENTER(
"Query_cache::ask_handler_allowance");
3765 for (; tables_used; tables_used= tables_used->next_global)
3769 if (!(table= tables_used->table))
3771 handler= table->file;
3780 DBUG_ASSERT(table->s->db_type() == heap_hton ||
3781 table->s->db_type() == myisam_hton);
3800 table->s->normalized_path.str,
3801 table->s->normalized_path.length,
3802 &tables_used->callback_func,
3803 &tables_used->engine_data))
3805 DBUG_PRINT(
"qcache", (
"Handler does not allow caching for %s.%s",
3806 tables_used->db, tables_used->alias));
3807 thd->lex->safe_to_cache_query= 0;
3826 void Query_cache::pack_cache()
3828 DBUG_ENTER(
"Query_cache::pack_cache");
3830 DBUG_EXECUTE(
"check_querycache",query_cache.check_integrity(1););
3844 ok = move_by_type(&border, &before, &gap, block);
3846 }
while (ok && block != first_block);
3851 new_block->init(gap);
3853 new_block->pnext = before->pnext;
3854 before->pnext = new_block;
3855 new_block->pprev = before;
3856 new_block->pnext->pprev = new_block;
3857 insert_into_free_memory_list(new_block);
3862 DBUG_EXECUTE(
"check_querycache",query_cache.check_integrity(1););
3867 my_bool Query_cache::move_by_type(uchar **border,
3871 DBUG_ENTER(
"Query_cache::move_by_type");
3874 switch (block->type) {
3875 case Query_cache_block::FREE:
3877 DBUG_PRINT(
"qcache", (
"block 0x%lx FREE", (ulong) block));
3880 *border = (uchar *) block;
3881 *before = block->pprev;
3882 DBUG_PRINT(
"qcache", (
"gap beginning here"));
3884 exclude_from_free_memory_list(block);
3885 *gap +=block->length;
3886 block->pprev->pnext=block->pnext;
3887 block->pnext->pprev=block->pprev;
3890 DBUG_PRINT(
"qcache", (
"added to gap (%lu)", *gap));
3893 case Query_cache_block::TABLE:
3895 HASH_SEARCH_STATE record_idx;
3896 DBUG_PRINT(
"qcache", (
"block 0x%lx TABLE", (ulong) block));
3899 ulong len = block->length, used = block->used;
3902 *tnext = list_root->
next;
3904 *next = block->next,
3905 *pprev = block->pprev,
3906 *pnext = block->pnext,
3908 uint tablename_offset = block->table()->table() - block->table()->db();
3909 char *data = (
char*) block->data();
3912 key=query_cache_table_get_key((uchar*) block, &key_length, 0);
3913 my_hash_first(&tables, (uchar*) key, key_length, &record_idx);
3916 new_block->init(len);
3917 new_block->type=Query_cache_block::TABLE;
3918 new_block->used=used;
3919 new_block->n_tables=1;
3920 memmove((
char*) new_block->data(), data, len-new_block->headers_len());
3921 relink(block, new_block, next, prev, pnext, pprev);
3922 if (tables_blocks == block)
3923 tables_blocks = new_block;
3927 nlist_root->
next = tnext;
3928 tnext->prev = nlist_root;
3929 nlist_root->prev = tprev;
3930 tprev->
next = nlist_root;
3931 DBUG_PRINT(
"qcache",
3932 (
"list_root: 0x%lx tnext 0x%lx tprev 0x%lx tprev->next 0x%lx tnext->prev 0x%lx",
3933 (ulong) list_root, (ulong) tnext, (ulong) tprev,
3934 (ulong)tprev->
next, (ulong)tnext->prev));
3940 for (;tnext != nlist_root; tnext=tnext->
next)
3941 tnext->parent= new_block_table;
3943 *before = new_block;
3945 new_block->table()->table(new_block->table()->db() + tablename_offset);
3947 my_hash_replace(&tables, &record_idx, (uchar*) new_block);
3949 DBUG_PRINT(
"qcache", (
"moved %lu bytes to 0x%lx, new gap at 0x%lx",
3950 len, (ulong) new_block, (ulong) *border));
3953 case Query_cache_block::QUERY:
3955 HASH_SEARCH_STATE record_idx;
3956 DBUG_PRINT(
"qcache", (
"block 0x%lx QUERY", (ulong) block));
3959 BLOCK_LOCK_WR(block);
3960 ulong len = block->length, used = block->used;
3961 TABLE_COUNTER_TYPE n_tables = block->n_tables;
3963 *next = block->next,
3964 *pprev = block->pprev,
3965 *pnext = block->pnext,
3967 char *data = (
char*) block->data();
3969 block->data())->result();
3972 key=query_cache_query_get_key((uchar*) block, &key_length, 0);
3973 my_hash_first(&queries, (uchar*) key, key_length, &record_idx);
3975 memmove((
char*) new_block->table(0), (
char*) block->table(0),
3977 block->query()->unlock_n_destroy();
3979 new_block->init(len);
3980 new_block->type=Query_cache_block::QUERY;
3981 new_block->used=used;
3982 new_block->n_tables=n_tables;
3983 memmove((
char*) new_block->data(), data, len - new_block->headers_len());
3984 relink(block, new_block, next, prev, pnext, pprev);
3985 if (queries_blocks == block)
3986 queries_blocks = new_block;
3988 *end_of_table_table= block->table(n_tables);
3989 uchar *beg_of_new_table_table= (uchar*) new_block->table(0);
3991 for (TABLE_COUNTER_TYPE j=0; j < n_tables; j++)
3996 if ((beg_of_table_table <= block_table->next) &&
3997 (block_table->
next < end_of_table_table))
3999 (((uchar*)block_table->
next) -
4000 ((uchar*)beg_of_table_table))))->prev=
4003 block_table->
next->prev= block_table;
4006 if ((beg_of_table_table <= block_table->prev) &&
4007 (block_table->prev < end_of_table_table))
4009 (((uchar*)block_table->prev) -
4010 ((uchar*)beg_of_table_table))))->
next=
4013 block_table->prev->
next = block_table;
4015 DBUG_PRINT(
"qcache", (
"after circle tt"));
4017 *before = new_block;
4018 new_block->query()->result(first_result_block);
4019 if (first_result_block != 0)
4024 result_block->result()->parent(new_block);
4025 result_block = result_block->next;
4026 }
while ( result_block != first_result_block );
4036 if (query_cache_tls != NULL)
4038 query_cache_tls->first_query_block= new_block;
4041 my_hash_replace(&queries, &record_idx, (uchar*) new_block);
4042 DBUG_PRINT(
"qcache", (
"moved %lu bytes to 0x%lx, new gap at 0x%lx",
4043 len, (ulong) new_block, (ulong) *border));
4046 case Query_cache_block::RES_INCOMPLETE:
4047 case Query_cache_block::RES_BEG:
4048 case Query_cache_block::RES_CONT:
4049 case Query_cache_block::RESULT:
4051 DBUG_PRINT(
"qcache", (
"block 0x%lx RES* (%d)", (ulong) block,
4052 (
int) block->type));
4056 BLOCK_LOCK_WR(query_block);
4058 Query_cache_block::block_type type= block->type;
4059 ulong len = block->length, used = block->used;
4061 *pnext = block->pnext,
4063 char *data = (
char*) block->data();
4065 new_block->init(len);
4066 new_block->type=
type;
4067 new_block->used=used;
4068 memmove((
char*) new_block->data(), data, len - new_block->headers_len());
4069 relink(block, new_block, next, prev, pnext, pprev);
4070 new_block->result()->parent(query_block);
4072 if (query->result() ==
block)
4073 query->result(new_block);
4075 *before = new_block;
4077 ulong free_space= new_block->length - new_block->used;
4078 free_space-= free_space % ALIGN_SIZE(1);
4079 if (query->result()->type == Query_cache_block::RESULT &&
4080 new_block->length > new_block->used &&
4081 *gap + free_space > min_allocation_unit &&
4082 new_block->length - free_space > min_allocation_unit)
4084 *border-= free_space;
4086 DBUG_PRINT(
"qcache",
4087 (
"rest of result free space added to gap (%lu)", *gap));
4088 new_block->length -= free_space;
4090 BLOCK_UNLOCK_WR(query_block);
4091 DBUG_PRINT(
"qcache", (
"moved %lu bytes to 0x%lx, new gap at 0x%lx",
4092 len, (ulong) new_block, (ulong) *border));
4096 DBUG_PRINT(
"error", (
"unexpected block type %d, block 0x%lx",
4097 (
int)block->type, (ulong) block));
4111 nblock->prev = nblock;
4112 nblock->next = nblock;
4116 nblock->prev = prev;
4121 nblock->next = next;
4124 nblock->pprev = pprev;
4125 nblock->pnext = pnext;
4126 pprev->pnext=nblock;
4127 pnext->pprev=nblock;
4131 my_bool Query_cache::join_results(ulong join_limit)
4133 my_bool has_moving = 0;
4134 DBUG_ENTER(
"Query_cache::join_results");
4136 if (queries_blocks != 0)
4138 DBUG_ASSERT(query_cache_size > 0);
4143 if (header->result() != 0 &&
4144 header->result()->type == Query_cache_block::RESULT &&
4145 header->length() > join_limit)
4148 get_free_block(ALIGN_SIZE(header->length()) +
4151 if (new_result_block != 0)
4155 ulong new_len = (header->length() +
4158 if (new_result_block->length >
4159 ALIGN_SIZE(new_len) + min_allocation_unit)
4160 split_block(new_result_block, ALIGN_SIZE(new_len));
4161 BLOCK_LOCK_WR(block);
4162 header->result(new_result_block);
4163 new_result_block->type = Query_cache_block::RESULT;
4164 new_result_block->n_tables = 0;
4165 new_result_block->used = new_len;
4167 new_result_block->next = new_result_block->prev = new_result_block;
4168 DBUG_PRINT(
"qcache", (
"new block %lu/%lu (%lu)",
4169 new_result_block->length,
4170 new_result_block->used,
4174 new_result->parent(block);
4175 uchar *write_to = (uchar*) new_result->data();
4179 ulong len = (result_block->used - result_block->headers_len() -
4181 DBUG_PRINT(
"loop", (
"add block %lu/%lu (%lu)",
4182 result_block->length,
4185 memcpy((
char *) write_to,
4186 (
char*) result_block->result()->data(),
4190 result_block = result_block->next;
4191 free_memory_block(old_result_block);
4192 }
while (result_block != first_result);
4193 BLOCK_UNLOCK_WR(block);
4196 block = block->next;
4197 }
while ( block != queries_blocks );
4199 DBUG_RETURN(has_moving);
4203 uint Query_cache::filename_2_table_key (
char *key,
const char *path,
4206 char tablename[FN_REFLEN+2], *filename, *dbname;
4207 DBUG_ENTER(
"Query_cache::filename_2_table_key");
4210 tablename[0]= FN_LIBCHAR;
4211 tablename[1]= FN_LIBCHAR;
4213 fn_format(tablename + 2, path,
"",
"", MY_REPLACE_EXT);
4214 filename= tablename + dirname_length(tablename + 2) + 2;
4216 for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ;
4217 *db_length= (filename - dbname) - 1;
4218 DBUG_PRINT(
"qcache", (
"table '%-.*s.%s'", *db_length, dbname, filename));
4220 DBUG_RETURN(static_cast<uint>(strmake(strmake(key, dbname,
4221 min<uint32>(*db_length,
4223 filename, NAME_LEN) - key) + 1);
4230 #if defined(DBUG_OFF) && !defined(USE_QUERY_CACHE_INTEGRITY_CHECK)
4232 void wreck(uint line,
const char *
message) { query_cache_size = 0; }
4234 void cache_dump() {}
4235 void queries_dump() {}
4236 void tables_dump() {}
4237 my_bool check_integrity(
bool not_locked) {
return 0; }
4239 const char *
name) {
return 0;}
4255 void Query_cache::wreck(uint line,
const char *
message)
4257 THD *thd=current_thd;
4258 DBUG_ENTER(
"Query_cache::wreck");
4259 query_cache_size = 0;
4261 DBUG_PRINT(
"error", (
" %s", message));
4262 DBUG_PRINT(
"warning", (
"=================================="));
4263 DBUG_PRINT(
"warning", (
"%5d QUERY CACHE WRECK => DISABLED",line));
4264 DBUG_PRINT(
"warning", (
"=================================="));
4266 thd->killed= THD::KILL_CONNECTION;
4274 void Query_cache::bins_dump()
4278 if (!initialized || query_cache_size == 0)
4280 DBUG_PRINT(
"qcache", (
"Query Cache not initialized"));
4284 DBUG_PRINT(
"qcache", (
"mem_bin_num=%u, mem_bin_steps=%u",
4285 mem_bin_num, mem_bin_steps));
4286 DBUG_PRINT(
"qcache", (
"-------------------------"));
4287 DBUG_PRINT(
"qcache", (
" size idx step"));
4288 DBUG_PRINT(
"qcache", (
"-------------------------"));
4289 for (i=0; i < mem_bin_steps; i++)
4291 DBUG_PRINT(
"qcache", (
"%10lu %3d %10lu", steps[i].size, steps[i].idx,
4292 steps[i].increment));
4294 DBUG_PRINT(
"qcache", (
"-------------------------"));
4295 DBUG_PRINT(
"qcache", (
" size num"));
4296 DBUG_PRINT(
"qcache", (
"-------------------------"));
4297 for (i=0; i < mem_bin_num; i++)
4299 DBUG_PRINT(
"qcache", (
"%10lu %3d 0x%lx", bins[i].size, bins[i].number,
4300 (ulong)&(bins[i])));
4301 if (bins[i].free_blocks)
4305 DBUG_PRINT(
"qcache", (
"\\-- %lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
4306 block->length, (ulong)block,
4307 (ulong)block->next, (ulong)block->prev,
4308 (ulong)block->pnext, (ulong)block->pprev));
4309 block = block->next;
4310 }
while ( block != bins[i].free_blocks );
4313 DBUG_PRINT(
"qcache", (
"-------------------------"));
4317 void Query_cache::cache_dump()
4319 if (!initialized || query_cache_size == 0)
4321 DBUG_PRINT(
"qcache", (
"Query Cache not initialized"));
4325 DBUG_PRINT(
"qcache", (
"-------------------------------------"));
4326 DBUG_PRINT(
"qcache", (
" length used t nt"));
4327 DBUG_PRINT(
"qcache", (
"-------------------------------------"));
4331 DBUG_PRINT(
"qcache",
4332 (
"%10lu %10lu %1d %2d 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
4333 i->length, i->used, (
int)i->type,
4334 i->n_tables, (ulong)i,
4335 (ulong)i->next, (ulong)i->prev, (ulong)i->pnext,
4338 }
while ( i != first_block );
4339 DBUG_PRINT(
"qcache", (
"-------------------------------------"));
4343 void Query_cache::queries_dump()
4348 DBUG_PRINT(
"qcache", (
"Query Cache not initialized"));
4352 DBUG_PRINT(
"qcache", (
"------------------"));
4353 DBUG_PRINT(
"qcache", (
" QUERIES"));
4354 DBUG_PRINT(
"qcache", (
"------------------"));
4355 if (queries_blocks != 0)
4361 char *str = (
char*) query_cache_query_get_key((uchar*)
block, &len, 0);
4362 len-= QUERY_CACHE_FLAGS_SIZE;
4363 Query_cache_query_flags
flags;
4364 memcpy(&flags, str+len, QUERY_CACHE_FLAGS_SIZE);
4366 DBUG_PRINT(
"qcache", (
"F: %u C: %u L: %lu T: '%s' (%lu) '%s' '%s'",
4367 flags.client_long_flag,
4368 flags.character_set_client_num,
4370 flags.time_zone->get_name()->ptr(),
4371 (ulong) len, str, strend(str)+1));
4372 DBUG_PRINT(
"qcache", (
"-b- 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx", (ulong) block,
4373 (ulong) block->next, (ulong) block->prev,
4374 (ulong)block->pnext, (ulong)block->pprev));
4375 memcpy(str + len, &flags, QUERY_CACHE_FLAGS_SIZE);
4376 for (TABLE_COUNTER_TYPE t= 0; t < block->n_tables; t++)
4379 DBUG_PRINT(
"qcache", (
"-t- '%s' '%s'", table->db(), table->table()));
4382 if (header->result())
4388 DBUG_PRINT(
"qcache", (
"-r- %u %lu/%lu 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx",
4389 (uint) result_block->type,
4390 result_block->length, result_block->used,
4391 (ulong) result_block,
4392 (ulong) result_block->next,
4393 (ulong) result_block->prev,
4394 (ulong) result_block->pnext,
4395 (ulong) result_block->pprev));
4396 result_block = result_block->next;
4397 }
while ( result_block != result_beg );
4399 }
while ((block=block->next) != queries_blocks);
4403 DBUG_PRINT(
"qcache", (
"no queries in list"));
4405 DBUG_PRINT(
"qcache", (
"------------------"));
4409 void Query_cache::tables_dump()
4411 if (!initialized || query_cache_size == 0)
4413 DBUG_PRINT(
"qcache", (
"Query Cache not initialized"));
4417 DBUG_PRINT(
"qcache", (
"--------------------"));
4418 DBUG_PRINT(
"qcache", (
"TABLES"));
4419 DBUG_PRINT(
"qcache", (
"--------------------"));
4420 if (tables_blocks != 0)
4426 DBUG_PRINT(
"qcache", (
"'%s' '%s'", table->db(), table->table()));
4427 table_block = table_block->next;
4428 }
while (table_block != tables_blocks);
4431 DBUG_PRINT(
"qcache", (
"no tables in list"));
4432 DBUG_PRINT(
"qcache", (
"--------------------"));
4444 my_bool Query_cache::check_integrity(
bool locked)
4448 DBUG_ENTER(
"check_integrity");
4453 if (my_hash_check(&queries))
4455 DBUG_PRINT(
"error", (
"queries hash is damaged"));
4459 if (my_hash_check(&tables))
4461 DBUG_PRINT(
"error", (
"tables hash is damaged"));
4465 DBUG_PRINT(
"qcache", (
"physical address check ..."));
4466 ulong free=0, used=0;
4474 DBUG_PRINT(
"qcache", (
"block 0x%lx, type %u...",
4475 (ulong) block, (uint) block->type));
4477 if ((((
long)block) % (
long) ALIGN_SIZE(1)) !=
4478 (((
long)first_block) % (
long)ALIGN_SIZE(1)))
4481 (
"block 0x%lx do not aligned by %d", (ulong) block,
4482 (
int) ALIGN_SIZE(1)));
4486 if (block->pnext == first_block)
4488 if (((uchar*)block) + block->length !=
4489 ((uchar*)first_block) + query_cache_size)
4492 (
"block 0x%lx, type %u, ended at 0x%lx, but cache ended at 0x%lx",
4493 (ulong) block, (uint) block->type,
4494 (ulong) (((uchar*)block) + block->length),
4495 (ulong) (((uchar*)first_block) + query_cache_size)));
4500 if (((uchar*)block) + block->length != ((uchar*)block->pnext))
4503 (
"block 0x%lx, type %u, ended at 0x%lx, but next block begining at 0x%lx",
4504 (ulong) block, (uint) block->type,
4505 (ulong) (((uchar*)block) + block->length),
4506 (ulong) ((uchar*)block->pnext)));
4508 if (block->type == Query_cache_block::FREE)
4509 free+= block->length;
4511 used+= block->length;
4512 switch(block->type) {
4513 case Query_cache_block::FREE:
4518 if (((uchar*)bin) < ((uchar*)bins) ||
4519 ((uchar*)bin) >= ((uchar*)first_block))
4522 (
"free block 0x%lx have bin pointer 0x%lx beyaond of bins array bounds [0x%lx,0x%lx]",
4526 (ulong) first_block));
4531 int idx = (((uchar*)bin) - ((uchar*)bins)) /
4533 if (in_list(bins[idx].free_blocks, block,
"free memory"))
4538 case Query_cache_block::TABLE:
4539 if (in_list(tables_blocks, block,
"tables"))
4541 if (in_table_list(block->table(0), block->table(0),
"table list root"))
4544 case Query_cache_block::QUERY:
4546 if (in_list(queries_blocks, block,
"query"))
4548 for (TABLE_COUNTER_TYPE j=0; j < block->n_tables; j++)
4553 (((uchar*)block_table->
parent) -
4556 if (in_table_list(block_table, block_table_root,
"table list"))
4561 case Query_cache_block::RES_INCOMPLETE:
4564 case Query_cache_block::RES_BEG:
4565 case Query_cache_block::RES_CONT:
4566 case Query_cache_block::RESULT:
4569 if (((uchar*)query_block) < ((uchar*)first_block) ||
4570 ((uchar*)query_block) >= (((uchar*)first_block) + query_cache_size))
4573 (
"result block 0x%lx have query block pointer 0x%lx beyaond of block pool bounds [0x%lx,0x%lx]",
4575 (ulong) query_block,
4576 (ulong) first_block,
4577 (ulong) (((uchar*)first_block) + query_cache_size)));
4582 BLOCK_LOCK_RD(query_block);
4583 if (in_list(queries_blocks, query_block,
"query from results"))
4585 if (in_list(query_block->query()->result(),
block,
4588 BLOCK_UNLOCK_RD(query_block);
4593 DBUG_PRINT(
"error", (
"block 0x%lx have incorrect type %u",
4594 (
long) block, block->type));
4598 block = block->pnext;
4599 }
while (block != first_block);
4601 if (used + free != query_cache_size)
4604 (
"used memory (%lu) + free memory (%lu) != query_cache_size (%lu)",
4605 used, free, query_cache_size));
4609 if (free != free_memory)
4612 (
"free memory (%lu) != free_memory (%lu)",
4613 free, free_memory));
4617 DBUG_PRINT(
"qcache", (
"check queries ..."));
4618 if ((block = queries_blocks))
4622 DBUG_PRINT(
"qcache", (
"block 0x%lx, type %u...",
4623 (ulong) block, (uint) block->type));
4625 uchar *key = query_cache_query_get_key((uchar*) block, &length, 0);
4626 uchar* val = my_hash_search(&queries, key, length);
4627 if (((uchar*)block) != val)
4629 DBUG_PRINT(
"error", (
"block 0x%lx found in queries hash like 0x%lx",
4630 (ulong) block, (ulong) val));
4632 if (in_blocks(block))
4640 DBUG_PRINT(
"qcache", (
"block 0x%lx, type %u...",
4641 (ulong) block, (uint) block->type));
4642 if (in_blocks(result_block))
4645 result_block = result_block->next;
4646 }
while (result_block != results);
4648 block = block->next;
4649 }
while (block != queries_blocks);
4652 DBUG_PRINT(
"qcache", (
"check tables ..."));
4653 if ((block = tables_blocks))
4657 DBUG_PRINT(
"qcache", (
"block 0x%lx, type %u...",
4658 (ulong) block, (uint) block->type));
4660 uchar *key = query_cache_table_get_key((uchar*) block, &length, 0);
4661 uchar* val = my_hash_search(&tables, key, length);
4662 if (((uchar*)block) != val)
4664 DBUG_PRINT(
"error", (
"block 0x%lx found in tables hash like 0x%lx",
4665 (ulong) block, (ulong) val));
4668 if (in_blocks(block))
4671 }
while (block != tables_blocks);
4674 DBUG_PRINT(
"qcache", (
"check free blocks"));
4675 for (i = 0; i < mem_bin_num; i++)
4677 if ((block = bins[i].free_blocks))
4682 DBUG_PRINT(
"qcache", (
"block 0x%lx, type %u...",
4683 (ulong) block, (uint) block->type));
4684 if (in_blocks(block))
4689 }
while (block != bins[i].free_blocks);
4690 if (count != bins[i].number)
4692 DBUG_PRINT(
"error", (
"bins[%d].number= %d, but bin have %d blocks",
4693 i, bins[i].number, count));
4698 DBUG_ASSERT(result == 0);
4701 DBUG_RETURN(result);
4712 if (block->pprev->pnext != block)
4715 (
"block 0x%lx in physical list is incorrect linked, prev block 0x%lx refered as next to 0x%lx (check from 0x%lx)",
4716 (ulong) block, (ulong) block->pprev,
4717 (ulong) block->pprev->pnext,
4720 for (; block != point; block = block->pnext)
4721 DBUG_PRINT(
"error", (
"back trace 0x%lx", (ulong) block));
4725 block = block->pprev;
4726 }
while (block != first_block && block != point);
4727 if (block != first_block)
4730 (
"block 0x%lx (0x%lx<-->0x%lx) not owned by pysical list",
4731 (ulong) block, (ulong) block->pprev, (ulong )block->pnext));
4740 if (block->pnext->pprev != block)
4743 (
"block 0x%lx in physicel list is incorrect linked, next block 0x%lx refered as prev to 0x%lx (check from 0x%lx)",
4744 (ulong) block, (ulong) block->pnext,
4745 (ulong) block->pnext->pprev,
4748 for (; block != point; block = block->pprev)
4749 DBUG_PRINT(
"error", (
"back trace 0x%lx", (ulong) block));
4753 block = block->pnext;
4754 }
while (block != first_block);
4769 if (block->prev->next != block)
4772 (
"block 0x%lx in list '%s' 0x%lx is incorrect linked, prev block 0x%lx refered as next to 0x%lx (check from 0x%lx)",
4773 (ulong) block, name, (ulong) root, (ulong) block->prev,
4774 (ulong) block->prev->next,
4777 for (; block != point; block = block->next)
4778 DBUG_PRINT(
"error", (
"back trace 0x%lx", (ulong) block));
4782 block = block->prev;
4783 }
while (block != root && block != point);
4787 (
"block 0x%lx (0x%lx<-->0x%lx) not owned by list '%s' 0x%lx",
4789 (ulong) block->prev, (ulong) block->next,
4790 name, (ulong) root));
4798 if (block->next->prev != block)
4801 (
"block 0x%lx in list '%s' 0x%lx is incorrect linked, next block 0x%lx refered as prev to 0x%lx (check from 0x%lx)",
4802 (ulong) block, name, (ulong) root, (ulong) block->next,
4803 (ulong) block->next->prev,
4806 for (; block != point; block = block->prev)
4807 DBUG_PRINT(
"error", (
"back trace 0x%lx", (ulong) block));
4811 block = block->next;
4812 }
while (block != root);
4818 const char * call,
const char *
descr)
4820 DBUG_PRINT(
"qcache", (
"%s: %s: node: 0x%lx", call, descr, (ulong) node));
4821 DBUG_PRINT(
"qcache", (
"%s: %s: node block: 0x%lx",
4822 call, descr, (ulong) node->
block()));
4823 DBUG_PRINT(
"qcache", (
"%s: %s: next: 0x%lx", call, descr,
4824 (ulong) node->
next));
4825 DBUG_PRINT(
"qcache", (
"%s: %s: prev: 0x%lx", call, descr,
4826 (ulong) node->prev));
4835 dump_node(root, name,
"parameter root");
4839 dump_node(table, name,
"list element << ");
4840 if (table->prev->
next != table)
4843 (
"table 0x%lx(0x%lx) in list '%s' 0x%lx(0x%lx) is incorrect linked, prev table 0x%lx(0x%lx) refered as next to 0x%lx(0x%lx) (check from 0x%lx(0x%lx))",
4844 (ulong) table, (ulong) table->
block(),
name,
4845 (ulong) root, (ulong) root->block(),
4846 (ulong) table->prev, (ulong) table->prev->block(),
4847 (ulong) table->prev->next,
4848 (ulong) table->prev->next->block(),
4849 (ulong) point, (ulong) point->block()));
4851 for (; table != point; table = table->next)
4852 DBUG_PRINT("error", ("back trace 0x%lx(0x%lx)",
4853 (ulong) table, (ulong) table->block()));
4857 table = table->prev;
4858 } while (table != root && table != point);
4862 (
"table 0x%lx(0x%lx) (0x%lx(0x%lx)<-->0x%lx(0x%lx)) not owned by list '%s' 0x%lx(0x%lx)",
4863 (ulong) table, (ulong) table->block(),
4864 (ulong) table->prev, (ulong) table->prev->block(),
4865 (ulong) table->next, (ulong) table->next->block(),
4866 name, (ulong) root, (ulong) root->block()));
4874 dump_node(table, name,
"list element >> ");
4875 if (table->next->prev != table)
4878 (
"table 0x%lx(0x%lx) in list '%s' 0x%lx(0x%lx) is incorrect linked, next table 0x%lx(0x%lx) refered as prev to 0x%lx(0x%lx) (check from 0x%lx(0x%lx))",
4879 (ulong) table, (ulong) table->block(),
4880 name, (ulong) root, (ulong) root->block(),
4881 (ulong) table->next, (ulong) table->next->block(),
4882 (ulong) table->next->prev,
4883 (ulong) table->next->prev->block(),
4884 (ulong) point, (ulong) point->block()));
4886 for (; table != point; table = table->prev)
4887 DBUG_PRINT("error", ("back trace 0x%lx(0x%lx)",
4888 (ulong) table, (ulong) table->block()));
4892 table = table->next;
4893 } while (table != root);