1 # name : response-time-distribution.patch
6 # Any small change to this file in the main branch
7 # should be done or reviewed by the maintainer!
8 diff -ruN a/CMakeLists.txt b/CMakeLists.txt
9 --- a/CMakeLists.txt 2010-12-03 20:58:24.000000000 +0300
10 +++ b/CMakeLists.txt 2011-01-16 20:11:28.000000000 +0300
12 OPTION (WITH_UNIT_TESTS "Compile MySQL with unit tests" ON)
13 MARK_AS_ADVANCED(CYBOZU BACKUP_TEST WITHOUT_SERVER DISABLE_SHARED)
16 +OPTION(WITHOUT_RESPONSE_TIME_DISTRIBUTION "If we want to have response_time_distribution" OFF)
17 +IF(WITHOUT_RESPONSE_TIME_DISTRIBUTION)
19 +ADD_DEFINITIONS(-DHAVE_RESPONSE_TIME_DISTRIBUTION)
22 OPTION(ENABLE_DEBUG_SYNC "Enable debug sync (debug builds only)" ON)
24 SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC")
25 diff -ruN a/include/mysql_com.h b/include/mysql_com.h
26 --- a/include/mysql_com.h 2010-12-03 20:58:24.000000000 +0300
27 +++ b/include/mysql_com.h 2011-01-16 18:53:58.000000000 +0300
29 #define REFRESH_FAST 32768 /* Intern flag */
31 /* RESET (remove all queries) from query cache */
32 -#define REFRESH_QUERY_CACHE 65536
33 -#define REFRESH_QUERY_CACHE_FREE 0x20000L /* pack query cache */
34 -#define REFRESH_DES_KEY_FILE 0x40000L
35 -#define REFRESH_USER_RESOURCES 0x80000L
36 +#define REFRESH_QUERY_CACHE 65536
37 +#define REFRESH_QUERY_CACHE_FREE 0x20000L /* pack query cache */
38 +#define REFRESH_DES_KEY_FILE 0x40000L
39 +#define REFRESH_USER_RESOURCES 0x80000L
40 +#define REFRESH_QUERY_RESPONSE_TIME 0x100000L /* response time distibution */
42 #define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */
43 #define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
44 diff -ruN a/patch_info/response-time-distribution.info b/patch_info/response-time-distribution.info
45 --- a/patch_info/response-time-distribution.info 1970-01-01 03:00:00.000000000 +0300
46 +++ b/patch_info/response-time-distribution.info 2011-01-16 18:53:59.000000000 +0300
48 +File=response-time-distribution.patch
49 +Name=Response time distribution
51 +Author=Percona <info@percona.com>
55 +2010-07-02 first version avaliable
56 +2010-09-15 add column 'total'
57 diff -ruN a/sql/CMakeLists.txt b/sql/CMakeLists.txt
58 --- a/sql/CMakeLists.txt 2010-12-03 20:58:26.000000000 +0300
59 +++ b/sql/CMakeLists.txt 2011-01-16 18:53:59.000000000 +0300
61 message.h mf_iocache.cc my_decimal.cc ../sql-common/my_time.c
62 mysqld.cc net_serv.cc keycaches.cc
63 ../sql-common/client_plugin.c
64 - opt_range.cc opt_range.h opt_sum.cc
65 + opt_range.cc opt_range.h query_response_time.h opt_sum.cc
66 ../sql-common/pack.c parse_file.cc password.c procedure.cc
67 protocol.cc records.cc repl_failsafe.cc rpl_filter.cc set_var.cc
68 slave.cc sp.cc sp_cache.cc sp_head.cc sp_pcontext.cc
70 sql_cache.cc sql_class.cc sql_client.cc sql_crypt.cc sql_crypt.h
71 sql_cursor.cc sql_db.cc sql_delete.cc sql_derived.cc sql_do.cc
72 sql_error.cc sql_handler.cc sql_help.cc sql_insert.cc sql_lex.cc
73 - sql_list.cc sql_load.cc sql_manager.cc sql_parse.cc
74 + sql_list.cc sql_load.cc sql_manager.cc sql_parse.cc query_response_time.cc
75 sql_partition.cc sql_plugin.cc sql_prepare.cc sql_rename.cc
76 debug_sync.cc debug_sync.h
77 sql_repl.cc sql_select.cc sql_show.cc sql_state.c sql_string.cc
78 diff -ruN a/sql/handler.h b/sql/handler.h
79 --- a/sql/handler.h 2011-01-16 18:53:33.000000000 +0300
80 +++ b/sql/handler.h 2011-01-16 18:54:00.000000000 +0300
83 SCH_REFERENTIAL_CONSTRAINTS,
85 + SCH_QUERY_RESPONSE_TIME,
87 SCH_SCHEMA_PRIVILEGES,
89 diff -ruN a/sql/lex.h b/sql/lex.h
90 --- a/sql/lex.h 2010-12-03 20:58:26.000000000 +0300
91 +++ b/sql/lex.h 2011-01-16 18:54:01.000000000 +0300
93 { "PURGE", SYM(PURGE)},
94 { "QUARTER", SYM(QUARTER_SYM)},
95 { "QUERY", SYM(QUERY_SYM)},
96 + { "QUERY_RESPONSE_TIME", SYM(QUERY_RESPONSE_TIME_SYM)},
97 { "QUICK", SYM(QUICK)},
98 { "RANGE", SYM(RANGE_SYM)},
99 { "READ", SYM(READ_SYM)},
100 diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
101 --- a/sql/mysqld.cc 2011-01-16 18:53:35.000000000 +0300
102 +++ b/sql/mysqld.cc 2011-01-17 02:22:27.000000000 +0300
104 #include "debug_sync.h"
105 #include "sql_callback.h"
107 +#include "query_response_time.h"
109 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
110 #include "../storage/perfschema/pfs_server.h"
111 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
113 MY_LOCALE *my_default_lc_messages;
114 MY_LOCALE *my_default_lc_time_names;
116 -SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
117 +SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache, have_response_time_distribution;
118 SHOW_COMP_OPTION have_geometry, have_rtree_keys;
119 SHOW_COMP_OPTION have_crypt, have_compress;
120 SHOW_COMP_OPTION have_profiling;
122 my_bool opt_enable_shared_memory;
123 HANDLE smem_event_connect_request= 0;
125 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
126 +ulong opt_query_response_time_range_base = QRT_DEFAULT_BASE;
127 +my_bool opt_enable_query_response_time_stats= 0;
128 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
130 my_bool opt_use_ssl = 0;
131 char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL,
132 @@ -1469,6 +1475,9 @@
133 my_free(opt_bin_logname);
134 bitmap_free(&temp_pool);
135 free_max_user_conn();
136 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
137 + query_response_time_free();
138 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
139 #ifdef HAVE_REPLICATION
142 @@ -3930,6 +3939,9 @@
143 if (!DEFAULT_ERRMSGS[0][0])
146 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
147 + query_response_time_init();
148 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
149 /* We have to initialize the storage engines before CSV logging */
152 @@ -6800,6 +6812,11 @@
154 have_query_cache=SHOW_OPTION_NO;
156 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
157 + have_response_time_distribution= SHOW_OPTION_YES;
158 +#else // HAVE_RESPONSE_TIME_DISTRIBUTION
159 + have_response_time_distribution= SHOW_OPTION_NO;
160 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
162 have_geometry=SHOW_OPTION_YES;
164 diff -ruN a/sql/mysqld.h b/sql/mysqld.h
165 --- a/sql/mysqld.h 2011-01-16 18:53:35.000000000 +0300
166 +++ b/sql/mysqld.h 2011-01-17 02:08:20.000000000 +0300
168 extern bool opt_disable_networking, opt_skip_show_db;
169 extern bool opt_skip_name_resolve;
170 extern bool opt_ignore_builtin_innodb;
171 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
172 +extern ulong opt_query_response_time_range_base;
173 +extern my_bool opt_enable_query_response_time_stats;
174 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
175 extern my_bool opt_character_set_client_handshake;
176 extern bool volatile abort_loop;
177 extern bool in_bootstrap;
178 diff -ruN a/sql/query_response_time.cc b/sql/query_response_time.cc
179 --- a/sql/query_response_time.cc 1970-01-01 03:00:00.000000000 +0300
180 +++ b/sql/query_response_time.cc 2011-01-17 02:13:08.000000000 +0300
182 +#include "mysql_version.h"
184 +#include <sys/types.h>
185 +#include <machine/atomic.h>
186 +#endif // __FreeBSD__
187 +#include "my_global.h"
188 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
189 +#include "mysql_com.h"
190 +#include "rpl_tblmap.h"
193 +#include "sql_show.h"
194 +#include "query_response_time.h"
196 +#define TIME_STRING_POSITIVE_POWER_LENGTH QRT_TIME_STRING_POSITIVE_POWER_LENGTH
197 +#define TIME_STRING_NEGATIVE_POWER_LENGTH 6
198 +#define TOTAL_STRING_POSITIVE_POWER_LENGTH QRT_TOTAL_STRING_POSITIVE_POWER_LENGTH
199 +#define TOTAL_STRING_NEGATIVE_POWER_LENGTH 6
200 +#define MINIMUM_BASE 2
201 +#define MAXIMUM_BASE QRT_MAXIMUM_BASE
202 +#define POSITIVE_POWER_FILLER QRT_POSITIVE_POWER_FILLER
203 +#define NEGATIVE_POWER_FILLER QRT_NEGATIVE_POWER_FILLER
204 +#define STRING_OVERFLOW QRT_STRING_OVERFLOW
205 +#define TIME_OVERFLOW QRT_TIME_OVERFLOW
206 +#define DEFAULT_BASE QRT_DEFAULT_BASE
208 +#define do_xstr(s) do_str(s)
209 +#define do_str(s) #s
210 +#define do_format(filler,width) "%" filler width "lld"
212 + Format strings for snprintf. Generate from:
213 + POSITIVE_POWER_FILLER and TIME_STRING_POSITIVE_POWER_LENGTH
214 + NEFATIVE_POWER_FILLER and TIME_STRING_NEGATIVE_POWER_LENGTH
216 +#define TIME_STRING_POSITIVE_POWER_FORMAT do_format(POSITIVE_POWER_FILLER,do_xstr(TIME_STRING_POSITIVE_POWER_LENGTH))
217 +#define TIME_STRING_NEGATIVE_POWER_FORMAT do_format(NEGATIVE_POWER_FILLER,do_xstr(TIME_STRING_NEGATIVE_POWER_LENGTH))
218 +#define TIME_STRING_FORMAT TIME_STRING_POSITIVE_POWER_FORMAT "." TIME_STRING_NEGATIVE_POWER_FORMAT
220 +#define TOTAL_STRING_POSITIVE_POWER_FORMAT do_format(POSITIVE_POWER_FILLER,do_xstr(TOTAL_STRING_POSITIVE_POWER_LENGTH))
221 +#define TOTAL_STRING_NEGATIVE_POWER_FORMAT do_format(NEGATIVE_POWER_FILLER,do_xstr(TOTAL_STRING_NEGATIVE_POWER_LENGTH))
222 +#define TOTAL_STRING_FORMAT TOTAL_STRING_POSITIVE_POWER_FORMAT "." TOTAL_STRING_NEGATIVE_POWER_FORMAT
224 +#define TIME_STRING_LENGTH QRT_TIME_STRING_LENGTH
225 +#define TIME_STRING_BUFFER_LENGTH (TIME_STRING_LENGTH + 1 /* '\0' */)
227 +#define TOTAL_STRING_LENGTH QRT_TOTAL_STRING_LENGTH
228 +#define TOTAL_STRING_BUFFER_LENGTH (TOTAL_STRING_LENGTH + 1 /* '\0' */)
231 + Calculate length of "log linear"
233 + (MINIMUM_BASE ^ result) <= (10 ^ STRING_POWER_LENGTH) < (MINIMUM_BASE ^ (result + 1))
236 + (MINIMUM_BASE ^ result) <= (10 ^ STRING_POWER_LENGTH)
238 + (MINIMUM_BASE ^ (result + 1)) > (10 ^ STRING_POWER_LENGTH)
241 + result <= LOG(MINIMUM_BASE, 10 ^ STRING_POWER_LENGTH)= STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10)
242 + result + 1 > LOG(MINIMUM_BASE, 10 ^ STRING_POWER_LENGTH)= STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10)
244 + 4) STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10) - 1 < result <= STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10)
246 + MINIMUM_BASE= 2 always, LOG(MINIMUM_BASE,10)= 3.3219280948873626, result= (int)3.3219280948873626 * STRING_POWER_LENGTH
248 + Last counter always use for time overflow
250 +#define POSITIVE_POWER_COUNT ((int)(3.32192809 * TIME_STRING_POSITIVE_POWER_LENGTH))
251 +#define NEGATIVE_POWER_COUNT ((int)(3.32192809 * TIME_STRING_NEGATIVE_POWER_LENGTH))
252 +#define OVERALL_POWER_COUNT (NEGATIVE_POWER_COUNT + 1 + POSITIVE_POWER_COUNT)
254 +#define MILLION ((unsigned long)1000 * 1000)
256 +namespace query_response_time
262 + utility() : m_base(0)
264 + m_max_dec_value= MILLION;
265 + for(int i= 0; TIME_STRING_POSITIVE_POWER_LENGTH > i; ++i)
266 + m_max_dec_value *= 10;
267 + setup(DEFAULT_BASE);
270 + uint base() const { return m_base; }
271 + uint negative_count() const { return m_negative_count; }
272 + uint positive_count() const { return m_positive_count; }
273 + uint bound_count() const { return m_bound_count; }
274 + ulonglong max_dec_value() const { return m_max_dec_value; }
275 + ulonglong bound(uint index) const { return m_bound[ index ]; }
277 + void setup(uint base)
283 + const ulonglong million= 1000 * 1000;
284 + ulonglong value= million;
285 + m_negative_count= 0;
288 + m_negative_count += 1;
291 + m_negative_count -= 1;
294 + m_positive_count= 0;
295 + while(value < m_max_dec_value)
297 + m_positive_count += 1;
300 + m_bound_count= m_negative_count + m_positive_count;
303 + for(uint i= 0; i < m_negative_count; ++i)
306 + m_bound[m_negative_count - i - 1]= value;
309 + for(uint i= 0; i < m_positive_count; ++i)
311 + m_bound[m_negative_count + i]= value;
318 + uint m_negative_count;
319 + uint m_positive_count;
320 + uint m_bound_count;
321 + ulonglong m_max_dec_value; /* for TIME_STRING_POSITIVE_POWER_LENGTH=7 is 10000000 */
322 + ulonglong m_bound[OVERALL_POWER_COUNT];
325 +void print_time(char* buffer, std::size_t buffer_size, std::size_t string_positive_power_length, const char* format, uint64 value)
327 + memset(buffer,'X',buffer_size);
328 + buffer[string_positive_power_length]= '.';
329 + ulonglong second= (value / MILLION);
330 + ulonglong microsecond= (value % MILLION);
331 + std::size_t result_length= snprintf(buffer,buffer_size,format,second,microsecond);
332 + if(result_length < 0)
334 + assert(sizeof(STRING_OVERFLOW) <= buffer_size);
335 + memcpy(buffer, STRING_OVERFLOW, sizeof(STRING_OVERFLOW));
338 + buffer[result_length]= 0;
341 +typedef uint64 TimeCounter;
342 +void add_time_atomic(TimeCounter* counter, uint64 time)
344 + __sync_fetch_and_add(counter,time);
346 +#endif // __x86_64__
348 +inline uint32 get_high(uint64 value)
350 + return ((value >> 32) << 32);
352 +inline uint32 get_low(uint64 value)
354 + return ((value << 32) >> 32);
357 +inline bool compare_and_swap(volatile uint32 *target, uint32 old, uint32 new_value)
359 + return atomic_cmpset_32(target,old,new_value);
361 +#else // __FreeBSD__
362 +inline bool compare_and_swap(volatile uint32* target, uint32 old, uint32 new_value)
364 + return __sync_bool_compare_and_swap(target,old,new_value);
366 +#endif // __FreeBSD__
370 + TimeCounter& operator=(uint64 time)
372 + this->m_high= get_high(time);
373 + this->m_low= get_low(time);
376 + operator uint64() const
378 + return ((static_cast<uint64>(m_high) << 32) + static_cast<uint64>(m_low));
380 + void add(uint64 time)
382 + uint32 time_high = get_high(time);
383 + uint32 time_low = get_low(time);
384 + uint64 time_low64= time_low;
387 + uint32 old_low= this->m_low;
388 + uint64 old_low64= old_low;
390 + uint64 new_low64= old_low64 + time_low64;
391 + uint32 new_low= (get_low(new_low64));
392 + bool add_high= (get_high(new_low64) != 0);
394 + if(!compare_and_swap(&m_low,old_low,new_low))
404 + __sync_fetch_and_add(&m_high,time_high);
413 +void add_time_atomic(TimeCounter* counter, uint64 time)
415 + counter->add(time);
419 +class time_collector
422 + time_collector(utility& u) : m_utility(&u)
425 + uint32 count(uint index) const { return m_count[index]; }
426 + uint64 total(uint index) const { return m_total[index]; }
430 + memset(&m_count,0,sizeof(m_count));
431 + memset((void*)&m_total,0,sizeof(m_total));
433 + void collect(uint64 time)
435 + bool no_collect= false;
436 + DBUG_EXECUTE_IF("response_time_distribution_log_only_more_300_milliseconds", { \
437 + no_collect= time < 300 * 1000; \
439 + if(no_collect) return;
441 + for(int count= m_utility->bound_count(); count > i; ++i)
443 + if(m_utility->bound(i) > time)
445 + __sync_fetch_and_add(&(m_count[i]),(uint32)1);
446 + add_time_atomic(&(m_total[i]),time);
452 + utility* m_utility;
453 + uint32 m_count[OVERALL_POWER_COUNT + 1];
454 + TimeCounter m_total[OVERALL_POWER_COUNT + 1];
460 + collector() : m_time(m_utility)
462 + m_utility.setup(DEFAULT_BASE);
468 + m_utility.setup(opt_query_response_time_range_base);
471 + int fill(THD* thd, TABLE_LIST *tables, COND *cond)
473 + DBUG_ENTER("fill_schema_query_response_time");
474 + TABLE *table= static_cast<TABLE*>(tables->table);
475 + Field **fields= table->field;
476 + for(uint i= 0, count= bound_count() + 1 /* with overflow */; count > i; ++i)
478 + char time[TIME_STRING_BUFFER_LENGTH];
479 + char total[TOTAL_STRING_BUFFER_LENGTH];
480 + if(i == bound_count())
482 + assert(sizeof(TIME_OVERFLOW) <= TIME_STRING_BUFFER_LENGTH);
483 + assert(sizeof(TIME_OVERFLOW) <= TOTAL_STRING_BUFFER_LENGTH);
484 + memcpy(time,TIME_OVERFLOW,sizeof(TIME_OVERFLOW));
485 + memcpy(total,TIME_OVERFLOW,sizeof(TIME_OVERFLOW));
489 + print_time(time,sizeof(time),TIME_STRING_POSITIVE_POWER_LENGTH,TIME_STRING_FORMAT,this->bound(i));
490 + print_time(total,sizeof(total),TOTAL_STRING_POSITIVE_POWER_LENGTH,TOTAL_STRING_FORMAT,this->total(i));
492 + fields[0]->store(time,strlen(time),system_charset_info);
493 + fields[1]->store(this->count(i));
494 + fields[2]->store(total,strlen(total),system_charset_info);
495 + if (schema_table_store_record(thd, table))
502 + void collect(ulonglong time)
504 + m_time.collect(time);
506 + uint bound_count() const
508 + return m_utility.bound_count();
510 + ulonglong bound(uint index)
512 + return m_utility.bound(index);
514 + ulonglong count(uint index)
516 + return m_time.count(index);
518 + ulonglong total(uint index)
520 + return m_time.total(index);
524 + time_collector m_time;
527 +static collector g_collector;
529 +} // namespace query_response_time
531 +void query_response_time_init()
535 +void query_response_time_free()
537 + query_response_time::g_collector.flush();
540 +void query_response_time_flush()
542 + query_response_time::g_collector.flush();
544 +void query_response_time_collect(ulonglong query_time)
546 + query_response_time::g_collector.collect(query_time);
549 +int query_response_time_fill(THD* thd, TABLE_LIST *tables, COND *cond)
551 + return query_response_time::g_collector.fill(thd,tables,cond);
553 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
554 diff -ruN a/sql/query_response_time.h b/sql/query_response_time.h
555 --- a/sql/query_response_time.h 1970-01-01 03:00:00.000000000 +0300
556 +++ b/sql/query_response_time.h 2011-01-17 02:13:34.000000000 +0300
558 +#ifndef QUERY_RESPONSE_TIME_H
559 +#define QUERY_RESPONSE_TIME_H
562 + Settings for query response time
566 + Maximum string length for (10 ^ (-1 * QRT_STRING_NEGATIVE_POWER_LENGTH)) in text representation.
567 + Example: for 6 is 0.000001
570 + Maximum string length for (10 ^ (QRT_STRING_POSITIVE_POWER_LENGTH + 1) - 1) in text representation.
571 + Example: for 7 is 9999999.0
573 +#define QRT_TIME_STRING_POSITIVE_POWER_LENGTH 7
574 +#define QRT_TOTAL_STRING_POSITIVE_POWER_LENGTH 7
577 + Minimum base for log - ALWAYS 2
578 + Maximum base for log:
580 +#define QRT_MAXIMUM_BASE 1000
583 + Filler for whole number (positive power)
585 + QRT_POSITIVE_POWER_FILLER ' '
586 + QRT_POSITIVE_POWER_LENGTH 7
587 + and number 7234 result is:
590 +#define QRT_POSITIVE_POWER_FILLER " "
592 + Filler for fractional number. Similiary to whole number
594 +#define QRT_NEGATIVE_POWER_FILLER "0"
597 + Message if string overflow (string overflow - internal error, this string say about bug in QRT)
599 +#define QRT_STRING_OVERFLOW "TOO BIG STRING"
602 + Message if time too big for statistic collecting (very long query)
604 +#define QRT_TIME_OVERFLOW "TOO LONG"
606 +#define QRT_DEFAULT_BASE 10
608 +#define QRT_TIME_STRING_LENGTH \
609 + max( (QRT_TIME_STRING_POSITIVE_POWER_LENGTH + 1 /* '.' */ + 6 /*QRT_TIME_STRING_NEGATIVE_POWER_LENGTH*/), \
610 + max( (sizeof(QRT_TIME_OVERFLOW) - 1), \
611 + (sizeof(QRT_STRING_OVERFLOW) - 1) ) )
613 +#define QRT_TOTAL_STRING_LENGTH \
614 + max( (QRT_TOTAL_STRING_POSITIVE_POWER_LENGTH + 1 /* '.' */ + 6 /*QRT_TOTAL_STRING_NEGATIVE_POWER_LENGTH*/), \
615 + max( (sizeof(QRT_TIME_OVERFLOW) - 1), \
616 + (sizeof(QRT_STRING_OVERFLOW) - 1) ) )
618 +extern ST_SCHEMA_TABLE query_response_time_table;
620 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
621 +extern void query_response_time_init ();
622 +extern void query_response_time_free ();
623 +extern void query_response_time_flush ();
624 +extern void query_response_time_collect(ulonglong query_time);
625 +extern int query_response_time_fill (THD* thd, TABLE_LIST *tables, COND *cond);
626 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
628 +#endif // QUERY_RESPONSE_TIME_H
629 diff -ruN a/sql/set_var.h b/sql/set_var.h
630 --- a/sql/set_var.h 2010-12-03 20:58:26.000000000 +0300
631 +++ b/sql/set_var.h 2011-01-17 02:20:59.000000000 +0300
634 extern SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen;
635 extern SHOW_COMP_OPTION have_query_cache;
636 +extern SHOW_COMP_OPTION have_response_time_distribution;
637 extern SHOW_COMP_OPTION have_geometry, have_rtree_keys;
638 extern SHOW_COMP_OPTION have_crypt;
639 extern SHOW_COMP_OPTION have_compress;
640 diff -ruN a/sql/sql_parse.cc b/sql/sql_parse.cc
641 --- a/sql/sql_parse.cc 2011-01-16 18:53:35.000000000 +0300
642 +++ b/sql/sql_parse.cc 2011-01-17 02:15:09.000000000 +0300
644 #include "sp_cache.h"
646 #include "sql_trigger.h"
647 +#include "query_response_time.h"
648 #include "transaction.h"
649 #include "sql_audit.h"
650 #include "sql_prepare.h"
651 @@ -1476,22 +1477,36 @@
652 Do not log administrative statements unless the appropriate option is
655 + #ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
656 + if (opt_enable_query_response_time_stats || thd->enable_slow_log)
657 +#else // HAVE_RESPONSE_TIME_DISTRIBUTION
658 if (thd->enable_slow_log)
659 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
661 - ulonglong end_utime_of_query= thd->current_utime();
662 - thd_proc_info(thd, "logging slow query");
664 - if (((thd->server_status & SERVER_QUERY_WAS_SLOW) ||
665 - ((thd->server_status &
666 - (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
667 - opt_log_queries_not_using_indexes &&
668 - !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) &&
669 - thd->examined_row_count >= thd->variables.min_examined_row_limit)
670 + ulonglong end_utime_of_query = thd->current_utime();
671 + ulonglong query_execution_time = end_utime_of_query - thd->utime_after_lock;
672 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
673 + if(opt_enable_query_response_time_stats)
675 + query_response_time_collect(query_execution_time);
677 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
678 + if (thd->enable_slow_log)
680 thd_proc_info(thd, "logging slow query");
681 - thd->status_var.long_query_count++;
682 - slow_log_print(thd, thd->query(), thd->query_length(),
683 - end_utime_of_query);
685 + if (((thd->server_status & SERVER_QUERY_WAS_SLOW) ||
686 + ((thd->server_status &
687 + (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
688 + opt_log_queries_not_using_indexes &&
689 + !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) &&
690 + thd->examined_row_count >= thd->variables.min_examined_row_limit)
692 + thd_proc_info(thd, "logging slow query");
693 + thd->status_var.long_query_count++;
694 + slow_log_print(thd, thd->query(), thd->query_length(),
695 + end_utime_of_query);
700 @@ -1610,6 +1625,7 @@
704 + case SCH_QUERY_RESPONSE_TIME:
705 case SCH_COLLATION_CHARACTER_SET_APPLICABILITY:
706 case SCH_USER_PRIVILEGES:
707 case SCH_SCHEMA_PRIVILEGES:
708 diff -ruN a/sql/sql_reload.cc b/sql/sql_reload.cc
709 --- a/sql/sql_reload.cc 2010-12-03 20:58:26.000000000 +0300
710 +++ b/sql/sql_reload.cc 2011-01-17 02:16:19.000000000 +0300
712 #include "hostname.h" // hostname_cache_refresh
713 #include "sql_repl.h" // reset_master, reset_slave
714 #include "debug_sync.h"
716 +#include "query_response_time.h"
719 Reload/resets privileges and the different caches.
722 if (options & REFRESH_USER_RESOURCES)
723 reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
724 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
725 + if (options & REFRESH_QUERY_RESPONSE_TIME)
727 + query_response_time_flush();
729 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
730 *write_to_binlog= tmp_write_to_binlog;
732 If the query was killed then this function must fail.
733 diff -ruN a/sql/sql_show.cc b/sql/sql_show.cc
734 --- a/sql/sql_show.cc 2011-01-16 18:53:35.000000000 +0300
735 +++ b/sql/sql_show.cc 2011-01-17 02:17:44.000000000 +0300
737 #include "event_data_objects.h"
740 +#include "query_response_time.h"
741 #include "lock.h" // MYSQL_OPEN_IGNORE_FLUSH
742 #include "debug_sync.h"
743 #include "datadict.h" // dd_frm_type()
744 @@ -7641,6 +7642,14 @@
748 +ST_FIELD_INFO query_response_time_fields_info[] =
750 + {"time", QRT_TIME_STRING_LENGTH, MYSQL_TYPE_STRING, 0, 0, "", SKIP_OPEN_TABLE },
751 + {"count", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, MY_I_S_UNSIGNED, "", SKIP_OPEN_TABLE },
752 + {"total", QRT_TIME_STRING_LENGTH, MYSQL_TYPE_STRING, 0, 0, "", SKIP_OPEN_TABLE },
753 + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE }
756 ST_SCHEMA_TABLE schema_tables[]=
758 {"CHARACTER_SETS", charsets_fields_info, create_schema_table,
759 @@ -7694,6 +7703,13 @@
760 1, 9, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY},
761 {"ROUTINES", proc_fields_info, create_schema_table,
762 fill_schema_proc, make_proc_old_format, 0, -1, -1, 0, 0},
763 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
764 + {"QUERY_RESPONSE_TIME", query_response_time_fields_info, create_schema_table,
765 + query_response_time_fill, make_old_format, 0, -1, -1, 0, 0},
767 + {"QUERY_RESPONSE_TIME", query_response_time_fields_info, create_schema_table,
768 + 0, make_old_format, 0, -1, -1, 0, 0},
769 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
770 {"SCHEMATA", schema_fields_info, create_schema_table,
771 fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0},
772 {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table,
773 diff -ruN a/sql/sql_yacc.yy b/sql/sql_yacc.yy
774 --- a/sql/sql_yacc.yy 2011-01-16 18:53:34.000000000 +0300
775 +++ b/sql/sql_yacc.yy 2011-01-17 02:19:03.000000000 +0300
776 @@ -1193,6 +1193,7 @@
780 +%token QUERY_RESPONSE_TIME_SYM
782 %token RANGE_SYM /* SQL-2003-R */
783 %token READS_SYM /* SQL-2003-R */
784 @@ -11089,6 +11090,15 @@
786 Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
788 + | QUERY_RESPONSE_TIME_SYM wild_and_where
790 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
792 + lex->sql_command= SQLCOM_SELECT;
793 + if (prepare_schema_table(YYTHD, lex, 0, SCH_QUERY_RESPONSE_TIME))
795 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
797 | CREATE PROCEDURE_SYM sp_name
800 @@ -11325,6 +11335,12 @@
801 { Lex->type|= REFRESH_STATUS; }
803 { Lex->type|= REFRESH_SLAVE; }
804 + | QUERY_RESPONSE_TIME_SYM
806 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
807 + Lex->type|= REFRESH_QUERY_RESPONSE_TIME;
808 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
811 { Lex->type|= REFRESH_MASTER; }
813 @@ -12610,6 +12626,7 @@
817 + | QUERY_RESPONSE_TIME_SYM {}
821 diff -ruN a/sql/sys_vars.cc b/sql/sys_vars.cc
822 --- a/sql/sys_vars.cc 2011-01-16 18:53:35.000000000 +0300
823 +++ b/sql/sys_vars.cc 2011-01-17 02:19:53.000000000 +0300
825 #include "../storage/perfschema/pfs_server.h"
826 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
828 +#include "query_response_time.h"
830 This forward declaration is needed because including sql_base.h
831 causes further includes. [TODO] Eliminate this forward declaration
832 @@ -1775,6 +1776,26 @@
834 #endif /* HAVE_QUERY_CACHE */
837 +static Sys_var_have Sys_have_response_time_distribution(
838 + "have_response_time_distribution", "have_response_time_distribution",
839 + READ_ONLY GLOBAL_VAR(have_response_time_distribution), NO_CMD_LINE);
841 +#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
842 +static Sys_var_mybool Sys_enable_query_response_time_stats(
843 + "enable_query_response_time_stats", "Enable or disable query response time statisics collecting",
844 + GLOBAL_VAR(opt_enable_query_response_time_stats), CMD_LINE(OPT_ARG),
847 +static Sys_var_ulong Sys_query_response_time_range_base(
848 + "query_response_time_range_base",
849 + "Select base of log for query_response_time ranges. WARNING: variable change affect only after flush",
850 + GLOBAL_VAR(opt_query_response_time_range_base),
851 + CMD_LINE(REQUIRED_ARG), VALID_RANGE(2, QRT_MAXIMUM_BASE),
852 + DEFAULT(QRT_DEFAULT_BASE),
854 +#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
856 static Sys_var_mybool Sys_secure_auth(
858 "Disallow authentication for accounts that have old (pre-4.1) "