27 #include "keycaches.h"
28 #include "sql_optimizer.h"
29 #include "opt_explain.h"
31 #include <thr_alarm.h>
32 #if defined(HAVE_MALLOC_INFO) && defined(HAVE_MALLOC_H)
34 #elif defined(HAVE_MALLOC_INFO) && defined(HAVE_SYS_MALLOC_H)
35 #include <sys/malloc.h>
38 #ifdef HAVE_EVENT_SCHEDULER
42 #include "global_threads.h"
43 #include "table_cache.h"
45 const char *lock_descriptions[TL_WRITE_ONLY + 1] =
49 "Low priority read lock",
51 "High priority read lock",
52 "Read lock without concurrent inserts",
53 "Write lock that allows other writers",
54 "Concurrent insert lock",
55 "Lock used by delayed insert",
57 "Low priority write lock",
58 "High priority write lock",
59 "Highest priority write lock"
66 print_where(
Item *cond,
const char *info, enum_query_type query_type)
69 String str(buff,(uint32)
sizeof(buff), system_charset_info);
72 cond->
print(&str, query_type);
76 (void) fprintf(DBUG_FILE,
"\nWHERE:(%s) %p ", info, cond);
77 (void) fputs(str.ptr(),DBUG_FILE);
78 (void) fputc(
'\n',DBUG_FILE);
84 static void print_cached_tables(
void)
91 printf(
"\nCurrent refresh version: %ld\n",refresh_version);
92 if (my_hash_check(&table_def_cache))
93 printf(
"Error: Table definition hash table is corrupted\n");
102 TEST_join(
JOIN *join)
105 DBUG_ENTER(
"TEST_join");
112 for (i= 0; i < join->
tables; i++)
115 for (ref= 0; ref < tab->ref.
key_parts; ref++)
117 ref_key_parts[
i].append(tab->ref.
items[ref]->full_name());
118 ref_key_parts[
i].append(
" ");
123 (void) fputs(
"\nInfo about JOIN\n",DBUG_FILE);
124 for (i=0 ; i < join->
tables ; i++)
130 char key_map_buff[128];
131 fprintf(DBUG_FILE,
"%-16.16s type: %-7s q_keys: %s refs: %d key: %d len: %d\n",
133 join_type_str[tab->type],
134 tab->
keys.print(key_map_buff),
140 char buf[MAX_KEY/8+1];
141 if (tab->use_quick == QS_DYNAMIC_RANGE)
143 " quick select checked for each record (keys: %s)\n",
144 tab->select->quick_keys.print(buf));
145 else if (tab->select->quick)
147 fprintf(DBUG_FILE,
" quick select used:\n");
148 tab->select->quick->dbug_dump(18, FALSE);
151 (
void) fputs(
" select used\n",DBUG_FILE);
156 " refs: %s\n", ref_key_parts[i].ptr());
168 #if !defined(DBUG_OFF) || defined(OPTIMIZER_TRACE)
169 if (unlikely(!trace->is_started()))
173 DBUG_PRINT(
"opt", (
"Key_use array (%zu elements)", keyuse_array->size()));
174 for (uint i= 0; i < keyuse_array->size(); i++)
176 const Key_use &keyuse= keyuse_array->at(i);
178 DBUG_PRINT(
"opt", (
"Key_use: optimize= %d used_tables=0x%llx "
179 "ref_table_rows= %lu keypart_map= %0lx",
183 add_utf8_table(keyuse.
table).
184 add_utf8(
"field", (keyuse.
keypart == FT_KEYPART) ?
"<fulltext>" :
186 key_part[keyuse.
keypart].field->field_name).
187 add(
"equals", keyuse.
val).
222 print_plan(
JOIN* join, uint idx,
double record_count,
double read_time,
223 double current_read_time,
const char *info)
238 "%s; idx: %u best: DBL_MAX atime: %g itime: %g count: %g\n",
239 info, idx, current_read_time, read_time, record_count);
244 "%s; idx :%u best: %g accumulated: %g increment: %g count: %g\n",
245 info, idx, join->
best_read, current_read_time, read_time,
250 fputs(
" POSITIONS: ", DBUG_FILE);
251 for (i= 0; i < idx ; i++)
253 pos = join->positions[
i];
254 table= pos.table->table;
256 fputs(table->alias, DBUG_FILE);
257 fputc(
' ', DBUG_FILE);
259 fputc(
'\n', DBUG_FILE);
267 fputs(
"BEST_POSITIONS: ", DBUG_FILE);
268 for (i= 0; i < idx ; i++)
270 pos= join->best_positions[
i];
271 table= pos.table->table;
273 fputs(table->alias, DBUG_FILE);
274 fputc(
' ', DBUG_FILE);
277 fputc(
'\n', DBUG_FILE);
280 fputs(
" BEST_REF: ", DBUG_FILE);
281 for (plan_nodes= join->best_ref ; *plan_nodes ; plan_nodes++)
283 join_table= (*plan_nodes);
284 fputs(join_table->table->s->table_name.str, DBUG_FILE);
285 fprintf(DBUG_FILE,
"(%lu,%lu,%lu)",
286 (ulong) join_table->found_records,
287 (ulong) join_table->records,
288 (ulong) join_table->read_time);
289 fputc(
' ', DBUG_FILE);
291 fputc(
'\n', DBUG_FILE);
299 static int dl_compare(
const void *p1,
const void *p2);
300 static int print_key_cache_status(
const char *
name,
KEY_CACHE *key_cache);
306 char table_name[FN_REFLEN];
308 const char *lock_text;
309 enum thr_lock_type type;
312 static int dl_compare(
const void *p1,
const void *p2)
314 TABLE_LOCK_INFO *a, *b;
316 a= (TABLE_LOCK_INFO *) p1;
317 b= (TABLE_LOCK_INFO *) p2;
319 if (a->thread_id > b->thread_id)
321 if (a->thread_id < b->thread_id)
323 if (a->waiting == b->waiting)
332 bool wait,
const char *text)
336 TABLE *table=(
TABLE *)data->debug_print_param;
337 if (table && table->s->tmp_table == NO_TMP_TABLE)
339 TABLE_LOCK_INFO table_lock_info;
340 table_lock_info.thread_id= table->in_use->thread_id;
341 memcpy(table_lock_info.table_name, table->s->table_cache_key.str,
342 table->s->table_cache_key.length);
343 table_lock_info.table_name[strlen(table_lock_info.table_name)]=
'.';
344 table_lock_info.waiting=wait;
345 table_lock_info.lock_text=text;
347 table_lock_info.type=table->reginfo.lock_type;
348 (void) push_dynamic(ar,(uchar*) &table_lock_info);
368 static void display_table_locks(
void)
374 (void) my_init_dynamic_array(&saved_table_locks,
sizeof(TABLE_LOCK_INFO),
377 for (list= thr_lock_thread_list; list; list= list_rest(list))
382 push_locks_into_array(&saved_table_locks, lock->write.data, FALSE,
384 push_locks_into_array(&saved_table_locks, lock->write_wait.data, TRUE,
386 push_locks_into_array(&saved_table_locks, lock->read.data, FALSE,
388 push_locks_into_array(&saved_table_locks, lock->read_wait.data, TRUE,
394 if (!saved_table_locks.elements)
397 saved_base= dynamic_element(&saved_table_locks, 0, TABLE_LOCK_INFO *);
398 my_qsort(saved_base, saved_table_locks.elements,
sizeof(TABLE_LOCK_INFO),
400 freeze_size(&saved_table_locks);
402 puts(
"\nThread database.table_name Locked/Waiting Lock_type\n");
405 for (i=0 ; i < saved_table_locks.elements ; i++)
407 TABLE_LOCK_INFO *dl_ptr=dynamic_element(&saved_table_locks,i,TABLE_LOCK_INFO*);
408 printf(
"%-8ld%-28.28s%-22s%s\n",
409 dl_ptr->thread_id,dl_ptr->table_name,dl_ptr->lock_text,lock_descriptions[(
int)dl_ptr->type]);
413 delete_dynamic(&saved_table_locks);
417 static int print_key_cache_status(
const char *
name,
KEY_CACHE *key_cache)
424 if (!key_cache->key_cache_inited)
426 printf(
"%s: Not in use\n", name);
431 Buffer_size: %10lu\n\
433 Division_limit: %10lu\n\
435 blocks used: %10lu\n\
436 not flushed: %10lu\n\
442 (ulong) key_cache->param_buff_size,
443 (ulong)key_cache->param_block_size,
444 (ulong)key_cache->param_division_limit,
445 (ulong)key_cache->param_age_threshold,
446 key_cache->blocks_used,key_cache->global_blocks_changed,
447 llstr(key_cache->global_cache_w_requests,llbuff1),
448 llstr(key_cache->global_cache_write,llbuff2),
449 llstr(key_cache->global_cache_r_requests,llbuff3),
450 llstr(key_cache->global_cache_read,llbuff4));
456 void mysql_print_status()
458 char current_dir[FN_REFLEN];
461 calc_sum_of_all_status(&tmp);
462 printf(
"\nStatus information:\n\n");
463 (void) my_getwd(current_dir,
sizeof(current_dir),MYF(0));
464 printf(
"Current dir: %s\n", current_dir);
465 printf(
"Running threads: %u Stack size: %ld\n", get_thread_count(),
466 (
long) my_thread_stack_size);
469 print_cached_tables();
472 puts(
"\nKey caches:");
473 process_key_caches(print_key_cache_status);
475 printf(
"\nhandler status:\n\
479 read_first: %10llu\n\
483 tmp.ha_read_key_count,
484 tmp.ha_read_next_count,
485 tmp.ha_read_rnd_count,
486 tmp.ha_read_first_count,
489 tmp.ha_update_count);
491 printf(
"\nTable status:\n\
492 Opened tables: %10lu\n\
493 Open tables: %10lu\n\
495 Open streams: %10lu\n",
496 (ulong) tmp.opened_tables,
498 (ulong) my_file_opened,
499 (ulong) my_stream_opened);
502 #ifndef DONT_USE_THR_ALARM
503 thr_alarm_info(&alarm_info);
504 printf(
"\nAlarm status:\n\
506 Max used alarms: %u\n\
507 Next alarm time: %lu\n",
508 alarm_info.active_alarms,
509 alarm_info.max_used_alarms,
510 alarm_info.next_alarm_time);
512 display_table_locks();
513 #ifdef HAVE_MALLOC_INFO
514 printf(
"\nMemory status:\n");
515 malloc_info(0, stdout);
518 #ifdef HAVE_EVENT_SCHEDULER
519 Events::dump_internal_status();
527 #ifdef EXTRA_DEBUG_DUMP_TABLE_LISTS
538 template <
class T>
class Unique_fifo_queue
542 void push_back(T *tbl)
547 for (
int i= 0; i < last; i++)
555 bool pop_first(T **elem)
559 *elem= elems[first++];
569 enum { MAX_ELEMS=1000};
575 class Dbug_table_list_dumper
578 Unique_fifo_queue<TABLE_LIST> tables_fifo;
579 Unique_fifo_queue<List<TABLE_LIST> > tbl_lists;
583 int dump_graph(st_select_lex *select_lex,
TABLE_LIST *first_leaf);
587 void dump_TABLE_LIST_graph(SELECT_LEX *select_lex,
TABLE_LIST* tl)
589 Dbug_table_list_dumper dumper;
590 dumper.dump_graph(select_lex, tl);
599 void Dbug_table_list_dumper::dump_one_struct(
TABLE_LIST *tbl)
601 fprintf(out,
"\"%p\" [\n", tbl);
602 fprintf(out,
" label = \"%p|", tbl);
603 fprintf(out,
"alias=%s|", tbl->alias? tbl->alias :
"NULL");
604 fprintf(out,
"<next_leaf>next_leaf=%p|", tbl->next_leaf);
605 fprintf(out,
"<next_local>next_local=%p|", tbl->next_local);
606 fprintf(out,
"<next_global>next_global=%p|", tbl->next_global);
607 fprintf(out,
"<embedding>embedding=%p", tbl->embedding);
609 if (tbl->nested_join)
610 fprintf(out,
"|<nested_j>nested_j=%p", tbl->nested_join);
612 fprintf(out,
"|<join_list>join_list=%p", tbl->join_list);
614 fprintf(out,
"|<on_expr>on_expr=%p", tbl->on_expr);
615 fprintf(out,
"\"\n");
616 fprintf(out,
" shape = \"record\"\n];\n\n");
620 fprintf(out,
"\n\"%p\":next_leaf -> \"%p\"[ color = \"#000000\" ];\n",
621 tbl, tbl->next_leaf);
622 tables_fifo.push_back(tbl->next_leaf);
626 fprintf(out,
"\n\"%p\":next_local -> \"%p\"[ color = \"#404040\" ];\n",
627 tbl, tbl->next_local);
628 tables_fifo.push_back(tbl->next_local);
630 if (tbl->next_global)
632 fprintf(out,
"\n\"%p\":next_global -> \"%p\"[ color = \"#808080\" ];\n",
633 tbl, tbl->next_global);
634 tables_fifo.push_back(tbl->next_global);
639 fprintf(out,
"\n\"%p\":embedding -> \"%p\"[ color = \"#FF0000\" ];\n",
640 tbl, tbl->embedding);
641 tables_fifo.push_back(tbl->embedding);
646 fprintf(out,
"\n\"%p\":join_list -> \"%p\"[ color = \"#0000FF\" ];\n",
647 tbl, tbl->join_list);
648 tbl_lists.push_back(tbl->join_list);
653 int Dbug_table_list_dumper::dump_graph(st_select_lex *select_lex,
656 DBUG_ENTER(
"Dbug_table_list_dumper::dump_graph");
661 sprintf(filename,
"tlist_tree%.3d.g", no);
662 if ((out= fopen(filename,
"rt")))
671 if (!(out= fopen(filename,
"wt")))
673 DBUG_PRINT(
"tree_dump", (
"Failed to create output file"));
677 DBUG_PRINT(
"tree_dump", (
"dumping tree to %s", filename));
679 fputs(
"digraph g {\n", out);
680 fputs(
"graph [", out);
681 fputs(
" rankdir = \"LR\"", out);
686 dump_one_struct(first_leaf);
687 while (tables_fifo.pop_first(&tbl))
689 dump_one_struct(tbl);
693 tbl_lists.push_back(&select_lex->top_join_list);
694 while (tbl_lists.pop_first(&plist))
696 fprintf(out,
"\"%p\" [\n", plist);
697 fprintf(out,
" bgcolor = \"\"");
698 fprintf(out,
" label = \"L %p\"", plist);
699 fprintf(out,
" shape = \"record\"\n];\n\n");
702 fprintf(out,
" { rank = same; ");
703 for (
TABLE_LIST *tl=first_leaf; tl; tl= tl->next_leaf)
704 fprintf(out,
" \"%p\"; ", tl);
705 fprintf(out,
"};\n");
710 filename[strlen(filename) - 1]= 0;
711 filename[strlen(filename) - 1]= 0;
712 sprintf(filename2,
"%s.query", filename);
714 if ((out= fopen(filename2,
"wt")))