]> git.pld-linux.org Git - packages/mysql.git/blame - response_time_distribution.patch
- fixed todo list
[packages/mysql.git] / response_time_distribution.patch
CommitLineData
b4e1fa2c
AM
1# name : response-time-distribution.patch
2# introduced : 12
3# maintainer : Oleg
4#
5#!!! notice !!!
6# Any small change to this file in the main branch
7# should be done or reviewed by the maintainer!
8diff -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
d8778560 11@@ -165,7 +165,12 @@
b4e1fa2c
AM
12 OPTION (WITH_UNIT_TESTS "Compile MySQL with unit tests" ON)
13 MARK_AS_ADVANCED(CYBOZU BACKUP_TEST WITHOUT_SERVER DISABLE_SHARED)
14
15-
16+OPTION(WITHOUT_RESPONSE_TIME_DISTRIBUTION "If we want to have response_time_distribution" OFF)
17+IF(WITHOUT_RESPONSE_TIME_DISTRIBUTION)
18+ELSE()
19+ADD_DEFINITIONS(-DHAVE_RESPONSE_TIME_DISTRIBUTION)
20+ENDIF()
21+
22 OPTION(ENABLE_DEBUG_SYNC "Enable debug sync (debug builds only)" ON)
23 IF(ENABLE_DEBUG_SYNC)
24 SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC")
25diff -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
28@@ -137,10 +137,11 @@
29 #define REFRESH_FAST 32768 /* Intern flag */
30
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 */
41
42 #define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */
43 #define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
44diff -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
47@@ -0,0 +1,9 @@
48+File=response-time-distribution.patch
49+Name=Response time distribution
50+Version=1.0
51+Author=Percona <info@percona.com>
52+License=GPL
53+Comment=
54+Changelog
55+2010-07-02 first version avaliable
56+2010-09-15 add column 'total'
57diff -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
60@@ -51,7 +51,7 @@
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
69@@ -59,7 +59,7 @@
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
78diff -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
df1b5770 81@@ -572,6 +572,7 @@
b4e1fa2c
AM
82 SCH_PROFILES,
83 SCH_REFERENTIAL_CONSTRAINTS,
84 SCH_PROCEDURES,
85+ SCH_QUERY_RESPONSE_TIME,
86 SCH_SCHEMATA,
87 SCH_SCHEMA_PRIVILEGES,
88 SCH_SESSION_STATUS,
89diff -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
92@@ -426,6 +426,7 @@
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)},
100diff -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
103@@ -69,6 +69,8 @@
104 #include "debug_sync.h"
105 #include "sql_callback.h"
106
107+#include "query_response_time.h"
108+
109 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
110 #include "../storage/perfschema/pfs_server.h"
111 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
df1b5770 112@@ -604,7 +606,7 @@
b4e1fa2c
AM
113 MY_LOCALE *my_default_lc_messages;
114 MY_LOCALE *my_default_lc_time_names;
115
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;
df1b5770 121@@ -905,6 +907,10 @@
b4e1fa2c
AM
122 my_bool opt_enable_shared_memory;
123 HANDLE smem_event_connect_request= 0;
124 #endif
125+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
126+ulong opt_query_response_time_range_base = QRT_DEFAULT_BASE;
d8778560 127+my_bool opt_query_response_time_stats= 0;
b4e1fa2c
AM
128+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
129
130 my_bool opt_use_ssl = 0;
131 char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL,
df1b5770 132@@ -1473,6 +1479,9 @@
b4e1fa2c
AM
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
140 end_slave_list();
141 #endif
df1b5770 142@@ -3944,6 +3953,9 @@
b4e1fa2c
AM
143 if (!DEFAULT_ERRMSGS[0][0])
144 unireg_abort(1);
145
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 */
150 if (ha_init())
151 {
df1b5770 152@@ -6819,6 +6831,11 @@
b4e1fa2c
AM
153 #else
154 have_query_cache=SHOW_OPTION_NO;
155 #endif
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
161 #ifdef HAVE_SPATIAL
162 have_geometry=SHOW_OPTION_YES;
163 #else
164diff -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
167@@ -98,6 +98,10 @@
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;
d8778560 173+extern my_bool opt_query_response_time_stats;
b4e1fa2c
AM
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;
178diff -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
181@@ -0,0 +1,372 @@
182+#include "mysql_version.h"
183+#ifdef __FreeBSD__
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"
191+#include "table.h"
192+#include "field.h"
193+#include "sql_show.h"
194+#include "query_response_time.h"
195+
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
207+
208+#define do_xstr(s) do_str(s)
209+#define do_str(s) #s
210+#define do_format(filler,width) "%" filler width "lld"
211+/*
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
215+*/
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
219+
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
223+
224+#define TIME_STRING_LENGTH QRT_TIME_STRING_LENGTH
225+#define TIME_STRING_BUFFER_LENGTH (TIME_STRING_LENGTH + 1 /* '\0' */)
226+
227+#define TOTAL_STRING_LENGTH QRT_TOTAL_STRING_LENGTH
228+#define TOTAL_STRING_BUFFER_LENGTH (TOTAL_STRING_LENGTH + 1 /* '\0' */)
229+
230+/*
231+ Calculate length of "log linear"
232+ 1)
233+ (MINIMUM_BASE ^ result) <= (10 ^ STRING_POWER_LENGTH) < (MINIMUM_BASE ^ (result + 1))
234+
235+ 2)
236+ (MINIMUM_BASE ^ result) <= (10 ^ STRING_POWER_LENGTH)
237+ and
238+ (MINIMUM_BASE ^ (result + 1)) > (10 ^ STRING_POWER_LENGTH)
239+
240+ 3)
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)
243+
244+ 4) STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10) - 1 < result <= STRING_POWER_LENGTH * LOG(MINIMUM_BASE,10)
245+
246+ MINIMUM_BASE= 2 always, LOG(MINIMUM_BASE,10)= 3.3219280948873626, result= (int)3.3219280948873626 * STRING_POWER_LENGTH
247+
248+ Last counter always use for time overflow
249+*/
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)
253+
254+#define MILLION ((unsigned long)1000 * 1000)
255+
256+namespace query_response_time
257+{
258+
259+class utility
260+{
261+public:
262+ utility() : m_base(0)
263+ {
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);
268+ }
269+public:
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 ]; }
276+public:
277+ void setup(uint base)
278+ {
279+ if(base != m_base)
280+ {
281+ m_base= base;
282+
283+ const ulonglong million= 1000 * 1000;
284+ ulonglong value= million;
285+ m_negative_count= 0;
286+ while(value > 0)
287+ {
288+ m_negative_count += 1;
289+ value /= m_base;
290+ }
291+ m_negative_count -= 1;
292+
293+ value= million;
294+ m_positive_count= 0;
295+ while(value < m_max_dec_value)
296+ {
297+ m_positive_count += 1;
298+ value *= m_base;
299+ }
300+ m_bound_count= m_negative_count + m_positive_count;
301+
302+ value= million;
303+ for(uint i= 0; i < m_negative_count; ++i)
304+ {
305+ value /= m_base;
306+ m_bound[m_negative_count - i - 1]= value;
307+ }
308+ value= million;
309+ for(uint i= 0; i < m_positive_count; ++i)
310+ {
311+ m_bound[m_negative_count + i]= value;
312+ value *= m_base;
313+ }
314+ }
315+ }
316+private:
317+ uint m_base;
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];
323+};
324+
325+void print_time(char* buffer, std::size_t buffer_size, std::size_t string_positive_power_length, const char* format, uint64 value)
326+{
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)
333+ {
334+ assert(sizeof(STRING_OVERFLOW) <= buffer_size);
335+ memcpy(buffer, STRING_OVERFLOW, sizeof(STRING_OVERFLOW));
336+ return;
337+ }
338+ buffer[result_length]= 0;
339+}
340+#ifdef __x86_64__
341+typedef uint64 TimeCounter;
342+void add_time_atomic(TimeCounter* counter, uint64 time)
343+{
344+ __sync_fetch_and_add(counter,time);
345+}
346+#endif // __x86_64__
347+#ifdef __i386__
348+inline uint32 get_high(uint64 value)
349+{
350+ return ((value >> 32) << 32);
351+}
352+inline uint32 get_low(uint64 value)
353+{
354+ return ((value << 32) >> 32);
355+}
356+#ifdef __FreeBSD__
357+inline bool compare_and_swap(volatile uint32 *target, uint32 old, uint32 new_value)
358+{
359+ return atomic_cmpset_32(target,old,new_value);
360+}
361+#else // __FreeBSD__
362+inline bool compare_and_swap(volatile uint32* target, uint32 old, uint32 new_value)
363+{
364+ return __sync_bool_compare_and_swap(target,old,new_value);
365+}
366+#endif // __FreeBSD__
367+class TimeCounter
368+{
369+public:
370+ TimeCounter& operator=(uint64 time)
371+ {
372+ this->m_high= get_high(time);
373+ this->m_low= get_low(time);
374+ return *this;
375+ }
376+ operator uint64() const
377+ {
378+ return ((static_cast<uint64>(m_high) << 32) + static_cast<uint64>(m_low));
379+ }
380+ void add(uint64 time)
381+ {
382+ uint32 time_high = get_high(time);
383+ uint32 time_low = get_low(time);
384+ uint64 time_low64= time_low;
385+ while(true)
386+ {
387+ uint32 old_low= this->m_low;
388+ uint64 old_low64= old_low;
389+
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);
393+
394+ if(!compare_and_swap(&m_low,old_low,new_low))
395+ {
396+ continue;
397+ }
398+ if(add_high)
399+ {
400+ ++time_high;
401+ }
402+ if(time_high > 0)
403+ {
404+ __sync_fetch_and_add(&m_high,time_high);
405+ }
406+ break;
407+ }
408+ }
409+private:
410+ uint32 m_low;
411+ uint32 m_high;
412+};
413+void add_time_atomic(TimeCounter* counter, uint64 time)
414+{
415+ counter->add(time);
416+}
417+#endif // __i386__
418+
419+class time_collector
420+{
421+public:
422+ time_collector(utility& u) : m_utility(&u)
423+ {
424+ }
425+ uint32 count(uint index) const { return m_count[index]; }
426+ uint64 total(uint index) const { return m_total[index]; }
427+public:
428+ void flush()
429+ {
430+ memset(&m_count,0,sizeof(m_count));
431+ memset((void*)&m_total,0,sizeof(m_total));
432+ }
433+ void collect(uint64 time)
434+ {
435+ bool no_collect= false;
436+ DBUG_EXECUTE_IF("response_time_distribution_log_only_more_300_milliseconds", { \
437+ no_collect= time < 300 * 1000; \
438+ });
439+ if(no_collect) return;
440+ int i= 0;
441+ for(int count= m_utility->bound_count(); count > i; ++i)
442+ {
443+ if(m_utility->bound(i) > time)
444+ {
445+ __sync_fetch_and_add(&(m_count[i]),(uint32)1);
446+ add_time_atomic(&(m_total[i]),time);
447+ break;
448+ }
449+ }
450+ }
451+private:
452+ utility* m_utility;
453+ uint32 m_count[OVERALL_POWER_COUNT + 1];
454+ TimeCounter m_total[OVERALL_POWER_COUNT + 1];
455+};
456+
457+class collector
458+{
459+public:
460+ collector() : m_time(m_utility)
461+ {
462+ m_utility.setup(DEFAULT_BASE);
463+ m_time.flush();
464+ }
465+public:
466+ void flush()
467+ {
468+ m_utility.setup(opt_query_response_time_range_base);
469+ m_time.flush();
470+ }
471+ int fill(THD* thd, TABLE_LIST *tables, COND *cond)
472+ {
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)
477+ {
478+ char time[TIME_STRING_BUFFER_LENGTH];
479+ char total[TOTAL_STRING_BUFFER_LENGTH];
480+ if(i == bound_count())
481+ {
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));
486+ }
487+ else
488+ {
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));
491+ }
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))
496+ {
497+ DBUG_RETURN(1);
498+ }
499+ }
500+ DBUG_RETURN(0);
501+ }
502+ void collect(ulonglong time)
503+ {
504+ m_time.collect(time);
505+ }
506+ uint bound_count() const
507+ {
508+ return m_utility.bound_count();
509+ }
510+ ulonglong bound(uint index)
511+ {
512+ return m_utility.bound(index);
513+ }
514+ ulonglong count(uint index)
515+ {
516+ return m_time.count(index);
517+ }
518+ ulonglong total(uint index)
519+ {
520+ return m_time.total(index);
521+ }
522+private:
523+ utility m_utility;
524+ time_collector m_time;
525+};
526+
527+static collector g_collector;
528+
529+} // namespace query_response_time
530+
531+void query_response_time_init()
532+{
533+}
534+
535+void query_response_time_free()
536+{
537+ query_response_time::g_collector.flush();
538+}
539+
540+void query_response_time_flush()
541+{
542+ query_response_time::g_collector.flush();
543+}
544+void query_response_time_collect(ulonglong query_time)
545+{
546+ query_response_time::g_collector.collect(query_time);
547+}
548+
549+int query_response_time_fill(THD* thd, TABLE_LIST *tables, COND *cond)
550+{
551+ return query_response_time::g_collector.fill(thd,tables,cond);
552+}
553+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
554diff -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
557@@ -0,0 +1,71 @@
558+#ifndef QUERY_RESPONSE_TIME_H
559+#define QUERY_RESPONSE_TIME_H
560+
561+/*
562+ Settings for query response time
563+*/
564+
565+/*
566+ Maximum string length for (10 ^ (-1 * QRT_STRING_NEGATIVE_POWER_LENGTH)) in text representation.
567+ Example: for 6 is 0.000001
568+ Always 2
569+
570+ Maximum string length for (10 ^ (QRT_STRING_POSITIVE_POWER_LENGTH + 1) - 1) in text representation.
571+ Example: for 7 is 9999999.0
572+*/
573+#define QRT_TIME_STRING_POSITIVE_POWER_LENGTH 7
574+#define QRT_TOTAL_STRING_POSITIVE_POWER_LENGTH 7
575+
576+/*
577+ Minimum base for log - ALWAYS 2
578+ Maximum base for log:
579+*/
580+#define QRT_MAXIMUM_BASE 1000
581+
582+/*
583+ Filler for whole number (positive power)
584+ Example: for
585+ QRT_POSITIVE_POWER_FILLER ' '
586+ QRT_POSITIVE_POWER_LENGTH 7
587+ and number 7234 result is:
588+ ' 7234'
589+*/
590+#define QRT_POSITIVE_POWER_FILLER " "
591+/*
592+ Filler for fractional number. Similiary to whole number
593+*/
594+#define QRT_NEGATIVE_POWER_FILLER "0"
595+
596+/*
597+ Message if string overflow (string overflow - internal error, this string say about bug in QRT)
598+*/
599+#define QRT_STRING_OVERFLOW "TOO BIG STRING"
600+
601+/*
602+ Message if time too big for statistic collecting (very long query)
603+*/
604+#define QRT_TIME_OVERFLOW "TOO LONG"
605+
606+#define QRT_DEFAULT_BASE 10
607+
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) ) )
612+
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) ) )
617+
618+extern ST_SCHEMA_TABLE query_response_time_table;
619+
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
627+
628+#endif // QUERY_RESPONSE_TIME_H
629diff -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
632@@ -293,6 +293,7 @@
633
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;
640diff -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
643@@ -88,6 +88,7 @@
644 #include "sp_cache.h"
645 #include "events.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"
d8778560 651@@ -1483,22 +1484,36 @@
b4e1fa2c
AM
652 Do not log administrative statements unless the appropriate option is
653 set.
654 */
655+ #ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
d8778560 656+ if (opt_query_response_time_stats || thd->enable_slow_log)
b4e1fa2c
AM
657+#else // HAVE_RESPONSE_TIME_DISTRIBUTION
658 if (thd->enable_slow_log)
659+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
660 {
661- ulonglong end_utime_of_query= thd->current_utime();
662- thd_proc_info(thd, "logging slow query");
663-
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
d8778560 673+ if(opt_query_response_time_stats)
b4e1fa2c
AM
674+ {
675+ query_response_time_collect(query_execution_time);
676+ }
677+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
678+ if (thd->enable_slow_log)
679 {
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);
684+
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)
691+ {
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);
696+ }
697 }
698 }
699 DBUG_VOID_RETURN;
d8778560 700@@ -1617,6 +1632,7 @@
b4e1fa2c
AM
701 case SCH_CHARSETS:
702 case SCH_ENGINES:
703 case SCH_COLLATIONS:
704+ case SCH_QUERY_RESPONSE_TIME:
705 case SCH_COLLATION_CHARACTER_SET_APPLICABILITY:
706 case SCH_USER_PRIVILEGES:
707 case SCH_SCHEMA_PRIVILEGES:
708diff -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
711@@ -25,7 +25,7 @@
712 #include "hostname.h" // hostname_cache_refresh
713 #include "sql_repl.h" // reset_master, reset_slave
714 #include "debug_sync.h"
715-
716+#include "query_response_time.h"
717
718 /**
719 Reload/resets privileges and the different caches.
d8778560 720@@ -282,6 +282,12 @@
b4e1fa2c
AM
721 #endif
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)
726+ {
727+ query_response_time_flush();
728+ }
729+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
d8778560
AM
730 if (*write_to_binlog != -1)
731 *write_to_binlog= tmp_write_to_binlog;
b4e1fa2c 732 /*
b4e1fa2c
AM
733diff -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
736@@ -50,6 +50,7 @@
737 #include "event_data_objects.h"
738 #endif
739 #include <my_dir.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()
df1b5770 744@@ -7689,6 +7690,14 @@
b4e1fa2c
AM
745
746 */
747
748+ST_FIELD_INFO query_response_time_fields_info[] =
749+ {
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 }
754+ };
755+
756 ST_SCHEMA_TABLE schema_tables[]=
757 {
758 {"CHARACTER_SETS", charsets_fields_info, create_schema_table,
df1b5770 759@@ -7742,6 +7751,13 @@
b4e1fa2c
AM
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},
766+#else
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,
773diff -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 @@
777 %token PURGE
778 %token QUARTER_SYM
779 %token QUERY_SYM
780+%token QUERY_RESPONSE_TIME_SYM
781 %token QUICK
782 %token RANGE_SYM /* SQL-2003-R */
783 %token READS_SYM /* SQL-2003-R */
784@@ -11089,6 +11090,15 @@
785 {
786 Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
787 }
788+ | QUERY_RESPONSE_TIME_SYM wild_and_where
789+ {
790+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
791+ LEX *lex= Lex;
792+ lex->sql_command= SQLCOM_SELECT;
793+ if (prepare_schema_table(YYTHD, lex, 0, SCH_QUERY_RESPONSE_TIME))
794+ MYSQL_YYABORT;
795+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
796+ }
797 | CREATE PROCEDURE_SYM sp_name
798 {
799 LEX *lex= Lex;
800@@ -11325,6 +11335,12 @@
801 { Lex->type|= REFRESH_STATUS; }
802 | SLAVE
803 { Lex->type|= REFRESH_SLAVE; }
804+ | QUERY_RESPONSE_TIME_SYM
805+ {
806+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
807+ Lex->type|= REFRESH_QUERY_RESPONSE_TIME;
808+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
809+ }
810 | MASTER_SYM
811 { Lex->type|= REFRESH_MASTER; }
812 | DES_KEY_FILE
813@@ -12610,6 +12626,7 @@
814 | PROXY_SYM {}
815 | QUARTER_SYM {}
816 | QUERY_SYM {}
817+ | QUERY_RESPONSE_TIME_SYM {}
818 | QUICK {}
819 | READ_ONLY_SYM {}
820 | REBUILD_SYM {}
821diff -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
824@@ -49,6 +49,7 @@
825 #include "../storage/perfschema/pfs_server.h"
826 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
827
828+#include "query_response_time.h"
829 /*
830 This forward declaration is needed because including sql_base.h
831 causes further includes. [TODO] Eliminate this forward declaration
d8778560 832@@ -1791,6 +1792,26 @@
b4e1fa2c
AM
833 DEFAULT(FALSE));
834 #endif /* HAVE_QUERY_CACHE */
835
836+
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);
840+
841+#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
d8778560
AM
842+static Sys_var_mybool Sys_query_response_time_stats(
843+ "query_response_time_stats", "Enable or disable query response time statisics collecting",
844+ GLOBAL_VAR(opt_query_response_time_stats), CMD_LINE(OPT_ARG),
b4e1fa2c
AM
845+ DEFAULT(FALSE));
846+
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),
853+ BLOCK_SIZE(1));
854+#endif // HAVE_RESPONSE_TIME_DISTRIBUTION
855+
856 static Sys_var_mybool Sys_secure_auth(
857 "secure_auth",
858 "Disallow authentication for accounts that have old (pre-4.1) "
This page took 0.224562 seconds and 4 git commands to generate.