]>
Commit | Line | Data |
---|---|---|
f11bce9d ER |
1 | diff -r 0b1f42e1aacf sql/event_scheduler.cc |
2 | --- a/sql/event_scheduler.cc Thu Dec 04 08:55:22 2008 -0800 | |
3 | +++ b/sql/event_scheduler.cc Thu Dec 04 08:55:29 2008 -0800 | |
4 | @@ -192,6 +192,7 @@ | |
5 | thd->client_capabilities|= CLIENT_MULTI_RESULTS; | |
6 | pthread_mutex_lock(&LOCK_thread_count); | |
7 | thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; | |
8 | + thd->write_to_slow_log = TRUE; | |
9 | pthread_mutex_unlock(&LOCK_thread_count); | |
10 | ||
11 | /* | |
12 | diff -r 0b1f42e1aacf sql/filesort.cc | |
13 | --- a/sql/filesort.cc Thu Dec 04 08:55:22 2008 -0800 | |
14 | +++ b/sql/filesort.cc Thu Dec 04 08:55:29 2008 -0800 | |
15 | @@ -188,6 +188,7 @@ | |
16 | { | |
17 | status_var_increment(thd->status_var.filesort_scan_count); | |
18 | } | |
19 | + thd->query_plan_flags|= QPLAN_FILESORT; | |
20 | #ifdef CAN_TRUST_RANGE | |
21 | if (select && select->quick && select->quick->records > 0L) | |
22 | { | |
23 | @@ -253,6 +254,7 @@ | |
24 | } | |
25 | else | |
26 | { | |
27 | + thd->query_plan_flags|= QPLAN_FILESORT_DISK; | |
28 | if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer) | |
29 | { | |
30 | x_free(table_sort.buffpek); | |
31 | @@ -1202,6 +1204,7 @@ | |
32 | DBUG_ENTER("merge_buffers"); | |
33 | ||
34 | status_var_increment(current_thd->status_var.filesort_merge_passes); | |
35 | + current_thd->query_plan_fsort_passes++; | |
36 | if (param->not_killable) | |
37 | { | |
38 | killed= ¬_killable; | |
39 | diff -r 0b1f42e1aacf sql/log.cc | |
40 | --- a/sql/log.cc Thu Dec 04 08:55:22 2008 -0800 | |
41 | +++ b/sql/log.cc Thu Dec 04 08:55:29 2008 -0800 | |
42 | @@ -963,7 +963,7 @@ | |
43 | /* fill in user_host value: the format is "%s[%s] @ %s [%s]" */ | |
44 | user_host_len= (strxnmov(user_host_buff, MAX_USER_HOST_SIZE, | |
45 | sctx->priv_user ? sctx->priv_user : "", "[", | |
46 | - sctx->user ? sctx->user : "", "] @ ", | |
47 | + sctx->user ? sctx->user : (thd->slave_thread ? "SQL_SLAVE" : ""), "] @ ", | |
48 | sctx->host ? sctx->host : "", " [", | |
49 | sctx->ip ? sctx->ip : "", "]", NullS) - | |
50 | user_host_buff); | |
51 | @@ -985,6 +985,13 @@ | |
52 | query= command_name[thd->command].str; | |
53 | query_length= command_name[thd->command].length; | |
54 | } | |
55 | + | |
56 | + if (!query_length) | |
57 | + { | |
58 | + thd->sent_row_count= thd->examined_row_count= 0; | |
59 | + thd->query_plan_flags= QPLAN_NONE; | |
60 | + thd->query_plan_fsort_passes= 0; | |
61 | + } | |
62 | ||
63 | for (current_handler= slow_log_handler_list; *current_handler ;) | |
64 | error= (*current_handler++)->log_slow(thd, current_time, thd->start_time, | |
65 | @@ -2242,16 +2249,31 @@ | |
66 | if (my_b_write(&log_file, (uchar*) "\n", 1)) | |
67 | tmp_errno= errno; | |
68 | } | |
69 | + | |
70 | /* For slow query log */ | |
71 | sprintf(query_time_buff, "%.6f", ulonglong2double(query_utime)/1000000.0); | |
72 | sprintf(lock_time_buff, "%.6f", ulonglong2double(lock_utime)/1000000.0); | |
73 | if (my_b_printf(&log_file, | |
74 | - "# Query_time: %s Lock_time: %s" | |
75 | - " Rows_sent: %lu Rows_examined: %lu\n", | |
76 | + "# Thread_id: %lu Schema: %s\n" \ | |
77 | + "# Query_time: %s Lock_time: %s Rows_sent: %lu Rows_examined: %lu\n", | |
78 | + (ulong) thd->thread_id, (thd->db ? thd->db : ""), | |
79 | query_time_buff, lock_time_buff, | |
80 | (ulong) thd->sent_row_count, | |
81 | (ulong) thd->examined_row_count) == (uint) -1) | |
82 | tmp_errno= errno; | |
83 | + if ((thd->variables.log_slow_verbosity & SLOG_V_QUERY_PLAN) && | |
84 | + my_b_printf(&log_file, | |
85 | + "# QC_Hit: %s Full_scan: %s Full_join: %s Tmp_table: %s Tmp_table_on_disk: %s\n" \ | |
86 | + "# Filesort: %s Filesort_on_disk: %s Merge_passes: %lu\n", | |
87 | + ((thd->query_plan_flags & QPLAN_QC) ? "Yes" : "No"), | |
88 | + ((thd->query_plan_flags & QPLAN_FULL_SCAN) ? "Yes" : "No"), | |
89 | + ((thd->query_plan_flags & QPLAN_FULL_JOIN) ? "Yes" : "No"), | |
90 | + ((thd->query_plan_flags & QPLAN_TMP_TABLE) ? "Yes" : "No"), | |
91 | + ((thd->query_plan_flags & QPLAN_TMP_DISK) ? "Yes" : "No"), | |
92 | + ((thd->query_plan_flags & QPLAN_FILESORT) ? "Yes" : "No"), | |
93 | + ((thd->query_plan_flags & QPLAN_FILESORT_DISK) ? "Yes" : "No"), | |
94 | + thd->query_plan_fsort_passes) == (uint) -1) | |
95 | + tmp_errno=errno; | |
96 | if (thd->db && strcmp(thd->db, db)) | |
97 | { // Database changed | |
98 | if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1) | |
99 | diff -r 0b1f42e1aacf sql/mysql_priv.h | |
100 | --- a/sql/mysql_priv.h Thu Dec 04 08:55:22 2008 -0800 | |
101 | +++ b/sql/mysql_priv.h Thu Dec 04 08:55:29 2008 -0800 | |
102 | @@ -597,6 +597,73 @@ | |
103 | #define WEEK_FIRST_WEEKDAY 4 | |
104 | ||
105 | #define STRING_BUFFER_USUAL_SIZE 80 | |
106 | + | |
107 | +/* Slow log */ | |
108 | + | |
109 | +struct msl_opts | |
110 | +{ | |
111 | + ulong val; | |
112 | + const char *name; | |
113 | +}; | |
114 | + | |
115 | +#define SLOG_V_QUERY_PLAN 1 << 1 | |
116 | +/* ... */ | |
117 | +#define SLOG_V_INVALID 1 << 31 | |
118 | +#define SLOG_V_NONE 1 << 0 | |
119 | + | |
120 | +static const struct msl_opts slog_verb[]= | |
121 | +{ | |
122 | + /* Basic flags */ | |
123 | + | |
124 | + { SLOG_V_QUERY_PLAN, "query_plan" }, | |
125 | + | |
126 | + /* End of baisc flags */ | |
127 | + | |
128 | + { 0, "" }, | |
129 | + | |
130 | + /* Complex flags */ | |
131 | + | |
132 | + { SLOG_V_QUERY_PLAN, "standard" }, | |
133 | + { SLOG_V_INVALID, "full" }, | |
134 | + | |
135 | + /* End of complex flags */ | |
136 | + | |
137 | + { SLOG_V_INVALID, (char *)0 } | |
138 | +}; | |
139 | + | |
140 | +#define QPLAN_NONE 0 | |
141 | +#define QPLAN_QC 1 << 0 | |
142 | +#define QPLAN_QC_NO 1 << 1 | |
143 | +#define QPLAN_FULL_SCAN 1 << 2 | |
144 | +#define QPLAN_FULL_JOIN 1 << 3 | |
145 | +#define QPLAN_TMP_TABLE 1 << 4 | |
146 | +#define QPLAN_TMP_DISK 1 << 5 | |
147 | +#define QPLAN_FILESORT 1 << 6 | |
148 | +#define QPLAN_FILESORT_DISK 1 << 7 | |
149 | +/* ... */ | |
150 | +#define QPLAN_MAX 1 << 31 | |
151 | + | |
152 | +#define SLOG_F_QC_NO QPLAN_QC_NO | |
153 | +#define SLOG_F_FULL_SCAN QPLAN_FULL_SCAN | |
154 | +#define SLOG_F_FULL_JOIN QPLAN_FULL_JOIN | |
155 | +#define SLOG_F_TMP_TABLE QPLAN_TMP_TABLE | |
156 | +#define SLOG_F_TMP_DISK QPLAN_TMP_DISK | |
157 | +#define SLOG_F_FILESORT QPLAN_FILESORT | |
158 | +#define SLOG_F_FILESORT_DISK QPLAN_FILESORT_DISK | |
159 | +#define SLOG_F_INVALID 1 << 31 | |
160 | +#define SLOG_F_NONE 0 | |
161 | + | |
162 | +static const struct msl_opts slog_filter[]= | |
163 | +{ | |
164 | + { SLOG_F_QC_NO, "qc_miss" }, | |
165 | + { SLOG_F_FULL_SCAN, "full_scan" }, | |
166 | + { SLOG_F_FULL_JOIN, "full_join" }, | |
167 | + { SLOG_F_TMP_TABLE, "tmp_table" }, | |
168 | + { SLOG_F_TMP_DISK, "tmp_table_on_disk" }, | |
169 | + { SLOG_F_FILESORT, "filesort" }, | |
170 | + { SLOG_F_FILESORT_DISK, "filesort_on_disk" }, | |
171 | + { SLOG_F_INVALID, (char *)0 } | |
172 | +}; | |
173 | ||
174 | /* | |
175 | Some defines for exit codes for ::is_equal class functions. | |
176 | diff -r 0b1f42e1aacf sql/mysqld.cc | |
177 | --- a/sql/mysqld.cc Thu Dec 04 08:55:22 2008 -0800 | |
178 | +++ b/sql/mysqld.cc Thu Dec 04 08:55:29 2008 -0800 | |
179 | @@ -5553,6 +5553,9 @@ | |
180 | OPT_SECURE_FILE_PRIV, | |
181 | OPT_MIN_EXAMINED_ROW_LIMIT, | |
182 | OPT_LOG_SLOW_SLAVE_STATEMENTS, | |
183 | + OPT_LOG_SLOW_RATE_LIMIT, | |
184 | + OPT_LOG_SLOW_VERBOSITY, | |
185 | + OPT_LOG_SLOW_FILTER, | |
a900d121 AM |
186 | #if defined(ENABLED_DEBUG_SYNC) |
187 | OPT_DEBUG_SYNC_TIMEOUT, | |
188 | #endif /* defined(ENABLED_DEBUG_SYNC) */ | |
f11bce9d ER |
189 | @@ -6480,6 +6483,17 @@ |
190 | (uchar**) 0, | |
191 | 0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100, | |
192 | 1, 100, 0, 1, 0}, | |
193 | + {"log_slow_filter", OPT_LOG_SLOW_FILTER, | |
194 | + "Log only the queries that followed certain execution plan. Multiple flags allowed in a comma-separated string. [qc_miss, full_scan, full_join, tmp_table, tmp_table_on_disk, filesort, filesort_on_disk]", | |
195 | + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, SLOG_F_NONE, 0, 0}, | |
196 | + {"log_slow_rate_limit", OPT_LOG_SLOW_RATE_LIMIT, | |
197 | + "Rate limit statement writes to slow log to only those from every (1/log_slow_rate_limit) session.", | |
198 | + (uchar**) &global_system_variables.log_slow_rate_limit, | |
199 | + (uchar**) &max_system_variables.log_slow_rate_limit, 0, GET_ULONG, | |
200 | + REQUIRED_ARG, 1, 1, ~0L, 0, 1L, 0}, | |
201 | + {"log_slow_verbosity", OPT_LOG_SLOW_VERBOSITY, | |
202 | + "Choose how verbose the messages to your slow log will be. Multiple flags allowed in a comma-separated string. [microtime, query_plan, innodb]", | |
203 | + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, SLOG_V_NONE, 0, 0}, | |
204 | {"long_query_time", OPT_LONG_QUERY_TIME, | |
205 | "Log all queries that have taken more than long_query_time seconds to execute to file. " | |
206 | "The argument will be treated as a decimal value with microsecond precission.", | |
207 | @@ -7556,6 +7570,10 @@ | |
208 | global_system_variables.old_passwords= 0; | |
209 | global_system_variables.old_alter_table= 0; | |
210 | global_system_variables.binlog_format= BINLOG_FORMAT_UNSPEC; | |
211 | + | |
212 | + global_system_variables.log_slow_verbosity= SLOG_V_NONE; | |
213 | + global_system_variables.log_slow_filter= SLOG_F_NONE; | |
214 | + | |
215 | /* | |
216 | Default behavior for 4.1 and 5.0 is to treat NULL values as unequal | |
217 | when collecting index statistics for MyISAM tables. | |
218 | @@ -8007,6 +8025,24 @@ | |
219 | case OPT_BOOTSTRAP: | |
220 | opt_noacl=opt_bootstrap=1; | |
221 | break; | |
222 | + case OPT_LOG_SLOW_FILTER: | |
223 | + if ((global_system_variables.log_slow_filter= | |
224 | + msl_flag_resolve_by_name(slog_filter, argument, | |
225 | + SLOG_F_NONE, SLOG_F_INVALID)) == SLOG_F_INVALID) | |
226 | + { | |
227 | + fprintf(stderr,"Invalid argument to log_slow_filter\n"); | |
228 | + exit(1); | |
229 | + } | |
230 | + break; | |
231 | + case OPT_LOG_SLOW_VERBOSITY: | |
232 | + if ((global_system_variables.log_slow_verbosity= | |
233 | + msl_flag_resolve_by_name(slog_verb, argument, | |
234 | + SLOG_V_NONE, SLOG_V_INVALID)) == SLOG_V_INVALID) | |
235 | + { | |
236 | + fprintf(stderr,"Invalid argument to log_slow_verbosity\n"); | |
237 | + exit(1); | |
238 | + } | |
239 | + break; | |
240 | case OPT_SERVER_ID: | |
241 | server_id_supplied = 1; | |
242 | break; | |
243 | diff -r 0b1f42e1aacf sql/set_var.cc | |
244 | --- a/sql/set_var.cc Thu Dec 04 08:55:22 2008 -0800 | |
245 | +++ b/sql/set_var.cc Thu Dec 04 08:55:29 2008 -0800 | |
246 | @@ -336,6 +336,20 @@ | |
247 | &SV::max_join_size, | |
248 | fix_max_join_size); | |
249 | #endif | |
250 | +static sys_var_thd_ulong sys_log_slow_rate_limit(&vars, "log_slow_rate_limit", | |
251 | + &SV::log_slow_rate_limit); | |
252 | +static sys_var_thd_msl_flag sys_log_slow_filter(&vars, "log_slow_filter", | |
253 | + &SV::log_slow_filter, | |
254 | + SLOG_F_NONE, | |
255 | + SLOG_F_NONE, | |
256 | + SLOG_F_INVALID, | |
257 | + slog_filter); | |
258 | +static sys_var_thd_msl_flag sys_log_slow_verbosity(&vars, "log_slow_verbosity", | |
259 | + &SV::log_slow_verbosity, | |
260 | + SLOG_V_NONE, | |
261 | + SLOG_V_NONE, | |
262 | + SLOG_V_INVALID, | |
263 | + slog_verb); | |
264 | static sys_var_long_ptr_global | |
265 | sys_max_prepared_stmt_count(&vars, "max_prepared_stmt_count", | |
266 | &max_prepared_stmt_count, | |
267 | @@ -3631,6 +3645,192 @@ | |
268 | #endif | |
269 | } | |
270 | ||
271 | +/* Slow log stuff */ | |
272 | + | |
273 | +ulong msl_option_resolve_by_name(const struct msl_opts *opts, const char *name, ulong len) | |
274 | +{ | |
275 | + ulong i; | |
276 | + | |
277 | + for (i=0; opts[i].name; i++) | |
278 | + { | |
279 | + if (!my_strnncoll(&my_charset_latin1, | |
280 | + (const uchar *)name, len, | |
281 | + (const uchar *)opts[i].name, strlen(opts[i].name))) | |
282 | + return opts[i].val; | |
283 | + } | |
284 | + return opts[i].val; | |
285 | +} | |
286 | + | |
287 | +ulong msl_flag_resolve_by_name(const struct msl_opts *opts, const char *names_list, | |
288 | + const ulong none_val, const ulong invalid_val) | |
289 | +{ | |
290 | + const char *p, *e; | |
291 | + ulong val= none_val; | |
292 | + | |
293 | + if (!*names_list) | |
294 | + return val; | |
295 | + | |
296 | + for (p= e= names_list; ; e++) | |
297 | + { | |
298 | + ulong i; | |
299 | + | |
300 | + if (*e != ',' && *e) | |
301 | + continue; | |
302 | + for (i=0; opts[i].name; i++) | |
303 | + { | |
304 | + if (!my_strnncoll(&my_charset_latin1, | |
305 | + (const uchar *)p, e - p, | |
306 | + (const uchar *)opts[i].name, strlen(opts[i].name))) | |
307 | + { | |
308 | + val= val | opts[i].val; | |
309 | + break; | |
310 | + } | |
311 | + } | |
312 | + if (opts[i].val == invalid_val) | |
313 | + return invalid_val; | |
314 | + if (!*e) | |
315 | + break; | |
316 | + p= e + 1; | |
317 | + } | |
318 | + return val; | |
319 | +} | |
320 | + | |
321 | +const char *msl_option_get_name(const struct msl_opts *opts, ulong val) | |
322 | +{ | |
323 | + for (ulong i=0; opts[i].name && opts[i].name[0]; i++) | |
324 | + { | |
325 | + if (opts[i].val == val) | |
326 | + return opts[i].name; | |
327 | + } | |
328 | + return "*INVALID*"; | |
329 | +} | |
330 | + | |
331 | +char *msl_flag_get_name(const struct msl_opts *opts, char *buf, ulong val) | |
332 | +{ | |
333 | + uint offset= 0; | |
334 | + | |
335 | + *buf= '\0'; | |
336 | + for (ulong i=0; opts[i].name && opts[i].name[0]; i++) | |
337 | + { | |
338 | + if (opts[i].val & val) | |
339 | + offset+= snprintf(buf+offset, STRING_BUFFER_USUAL_SIZE - offset - 1, | |
340 | + "%s%s", (offset ? "," : ""), opts[i].name); | |
341 | + } | |
342 | + return buf; | |
343 | +} | |
344 | + | |
345 | +/**************************************************************************** | |
346 | + Functions to handle log_slow_verbosity | |
347 | +****************************************************************************/ | |
348 | + | |
349 | +/* Based upon sys_var::check_enum() */ | |
350 | + | |
351 | +bool sys_var_thd_msl_option::check(THD *thd, set_var *var) | |
352 | +{ | |
353 | + char buff[STRING_BUFFER_USUAL_SIZE]; | |
354 | + String str(buff, sizeof(buff), &my_charset_latin1), *res; | |
355 | + | |
356 | + if (var->value->result_type() == STRING_RESULT) | |
357 | + { | |
358 | + ulong verb= this->invalid_val; | |
359 | + if (!(res=var->value->val_str(&str)) || | |
360 | + (var->save_result.ulong_value= | |
361 | + (ulong) (verb= msl_option_resolve_by_name(this->opts, res->ptr(), res->length()))) == this->invalid_val) | |
362 | + goto err; | |
363 | + return 0; | |
364 | + } | |
365 | + | |
366 | +err: | |
367 | + my_error(ER_WRONG_ARGUMENTS, MYF(0), var->var->name); | |
368 | + return 1; | |
369 | +} | |
370 | + | |
371 | +uchar *sys_var_thd_msl_option::value_ptr(THD *thd, enum_var_type type, | |
372 | + LEX_STRING *base) | |
373 | +{ | |
374 | + ulong val; | |
375 | + val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : | |
376 | + thd->variables.*offset); | |
377 | + const char *verbosity= msl_option_get_name(this->opts, val); | |
378 | + return (uchar *) verbosity; | |
379 | +} | |
380 | + | |
381 | + | |
382 | +void sys_var_thd_msl_option::set_default(THD *thd, enum_var_type type) | |
383 | +{ | |
384 | + if (type == OPT_GLOBAL) | |
385 | + global_system_variables.*offset= (ulong) this->default_val; | |
386 | + else | |
387 | + thd->variables.*offset= (ulong) (global_system_variables.*offset); | |
388 | +} | |
389 | + | |
390 | + | |
391 | +bool sys_var_thd_msl_option::update(THD *thd, set_var *var) | |
392 | +{ | |
393 | + if (var->type == OPT_GLOBAL) | |
394 | + global_system_variables.*offset= var->save_result.ulong_value; | |
395 | + else | |
396 | + thd->variables.*offset= var->save_result.ulong_value; | |
397 | + return 0; | |
398 | +} | |
399 | + | |
400 | +/**************************************************************************** | |
401 | + Functions to handle log_slow_filter | |
402 | +****************************************************************************/ | |
403 | + | |
404 | +/* Based upon sys_var::check_enum() */ | |
405 | + | |
406 | +bool sys_var_thd_msl_flag::check(THD *thd, set_var *var) | |
407 | +{ | |
408 | + char buff[2 * STRING_BUFFER_USUAL_SIZE]; | |
409 | + String str(buff, sizeof(buff), &my_charset_latin1), *res; | |
410 | + | |
411 | + if (var->value->result_type() == STRING_RESULT) | |
412 | + { | |
413 | + ulong filter= this->none_val; | |
414 | + if (!(res=var->value->val_str(&str)) || | |
415 | + (var->save_result.ulong_value= | |
416 | + (ulong) (filter= msl_flag_resolve_by_name(this->flags, res->ptr(), this->none_val, | |
417 | + this->invalid_val))) == this->invalid_val) | |
418 | + goto err; | |
419 | + return 0; | |
420 | + } | |
421 | + | |
422 | +err: | |
423 | + my_error(ER_WRONG_ARGUMENTS, MYF(0), var->var->name); | |
424 | + return 1; | |
425 | +} | |
426 | + | |
427 | +uchar *sys_var_thd_msl_flag::value_ptr(THD *thd, enum_var_type type, | |
428 | + LEX_STRING *base) | |
429 | +{ | |
430 | + ulong val; | |
431 | + val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : | |
432 | + thd->variables.*offset); | |
433 | + msl_flag_get_name(this->flags, this->flags_string, val); | |
434 | + return (uchar *) this->flags_string; | |
435 | +} | |
436 | + | |
437 | + | |
438 | +void sys_var_thd_msl_flag::set_default(THD *thd, enum_var_type type) | |
439 | +{ | |
440 | + if (type == OPT_GLOBAL) | |
441 | + global_system_variables.*offset= (ulong) this->default_val; | |
442 | + else | |
443 | + thd->variables.*offset= (ulong) (global_system_variables.*offset); | |
444 | +} | |
445 | + | |
446 | + | |
447 | +bool sys_var_thd_msl_flag::update(THD *thd, set_var *var) | |
448 | +{ | |
449 | + if (var->type == OPT_GLOBAL) | |
450 | + global_system_variables.*offset= var->save_result.ulong_value; | |
451 | + else | |
452 | + thd->variables.*offset= var->save_result.ulong_value; | |
453 | + return 0; | |
454 | +} | |
455 | + | |
456 | + | |
457 | /**************************************************************************** | |
458 | Functions to handle table_type | |
459 | ****************************************************************************/ | |
460 | diff -r 0b1f42e1aacf sql/set_var.h | |
461 | --- a/sql/set_var.h Thu Dec 04 08:55:22 2008 -0800 | |
462 | +++ b/sql/set_var.h Thu Dec 04 08:55:29 2008 -0800 | |
463 | @@ -1057,6 +1057,68 @@ | |
464 | bool update(THD *thd, set_var *var); | |
465 | }; | |
466 | ||
467 | +class sys_var_thd_msl_option :public sys_var_thd | |
468 | +{ | |
469 | +protected: | |
470 | + ulong SV::*offset; | |
471 | + const ulong none_val; | |
472 | + const ulong default_val; | |
473 | + const ulong invalid_val; | |
474 | + const struct msl_opts *opts; | |
475 | +public: | |
476 | + sys_var_thd_msl_option(sys_var_chain *chain, const char *name_arg, | |
477 | + ulong SV::*offset_arg, | |
478 | + const ulong none_val_arg, | |
479 | + const ulong default_val_arg, | |
480 | + const ulong invalid_val_arg, | |
481 | + const struct msl_opts *opts_arg) | |
482 | + :sys_var_thd(name_arg), offset(offset_arg), none_val(none_val_arg), | |
483 | + default_val(default_val_arg), invalid_val(invalid_val_arg), | |
484 | + opts(opts_arg) | |
485 | + { chain_sys_var(chain); } | |
486 | + bool check(THD *thd, set_var *var); | |
487 | + SHOW_TYPE show_type() { return SHOW_CHAR; } | |
488 | + bool check_update_type(Item_result type) | |
489 | + { | |
490 | + return type != STRING_RESULT; /* Only accept strings */ | |
491 | + } | |
492 | + void set_default(THD *thd, enum_var_type type); | |
493 | + bool update(THD *thd, set_var *var); | |
494 | + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); | |
495 | +}; | |
496 | + | |
497 | + | |
498 | +class sys_var_thd_msl_flag :public sys_var_thd | |
499 | +{ | |
500 | +protected: | |
501 | + char flags_string[2 * STRING_BUFFER_USUAL_SIZE]; | |
502 | + ulong SV::*offset; | |
503 | + const ulong none_val; | |
504 | + const ulong default_val; | |
505 | + const ulong invalid_val; | |
506 | + const struct msl_opts *flags; | |
507 | +public: | |
508 | + sys_var_thd_msl_flag(sys_var_chain *chain, const char *name_arg, | |
509 | + ulong SV::*offset_arg, | |
510 | + const ulong none_val_arg, | |
511 | + const ulong default_val_arg, | |
512 | + const ulong invalid_val_arg, | |
513 | + const struct msl_opts *flags_arg) | |
514 | + :sys_var_thd(name_arg), offset(offset_arg), none_val(none_val_arg), | |
515 | + default_val(default_val_arg), invalid_val(invalid_val_arg), | |
516 | + flags(flags_arg) | |
517 | + { chain_sys_var(chain); } | |
518 | + bool check(THD *thd, set_var *var); | |
519 | + SHOW_TYPE show_type() { return SHOW_CHAR; } | |
520 | + bool check_update_type(Item_result type) | |
521 | + { | |
522 | + return type != STRING_RESULT; /* Only accept strings */ | |
523 | + } | |
524 | + void set_default(THD *thd, enum_var_type type); | |
525 | + bool update(THD *thd, set_var *var); | |
526 | + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); | |
527 | +}; | |
528 | + | |
529 | ||
530 | /** | |
531 | Handler for setting the system variable --read-only. | |
532 | @@ -1323,3 +1385,10 @@ | |
533 | bool process_key_caches(process_key_cache_t func); | |
534 | void delete_elements(I_List<NAMED_LIST> *list, | |
535 | void (*free_element)(const char*, uchar*)); | |
536 | + | |
537 | +/* Slow log functions */ | |
538 | +ulong msl_option_resolve_by_name(const struct msl_opts *opts, const char *name, ulong len); | |
539 | +ulong msl_flag_resolve_by_name(const struct msl_opts *opts, const char *names_list, | |
540 | + const ulong none_val, const ulong invalid_val); | |
541 | +const char *msl_option_get_name(const struct msl_opts *opts, ulong val); | |
542 | +char *msl_flag_get_name(const struct msl_opts *opts, char *buf, ulong val); | |
543 | diff -r 0b1f42e1aacf sql/slave.cc | |
544 | --- a/sql/slave.cc Thu Dec 04 08:55:22 2008 -0800 | |
545 | +++ b/sql/slave.cc Thu Dec 04 08:55:29 2008 -0800 | |
546 | @@ -1561,6 +1561,7 @@ | |
547 | + MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */ | |
548 | thd->slave_thread = 1; | |
549 | thd->enable_slow_log= opt_log_slow_slave_statements; | |
550 | + thd->write_to_slow_log= opt_log_slow_slave_statements; | |
551 | set_slave_thread_options(thd); | |
552 | thd->client_capabilities = CLIENT_LOCAL_FILES; | |
553 | pthread_mutex_lock(&LOCK_thread_count); | |
554 | diff -r 0b1f42e1aacf sql/sql_cache.cc | |
555 | --- a/sql/sql_cache.cc Thu Dec 04 08:55:22 2008 -0800 | |
556 | +++ b/sql/sql_cache.cc Thu Dec 04 08:55:29 2008 -0800 | |
557 | @@ -1465,6 +1465,7 @@ | |
558 | ||
559 | thd->limit_found_rows = query->found_rows(); | |
560 | thd->status_var.last_query_cost= 0.0; | |
561 | + thd->query_plan_flags|= QPLAN_QC; | |
562 | thd->main_da.disable_status(); | |
563 | ||
564 | BLOCK_UNLOCK_RD(query_block); | |
565 | @@ -1473,6 +1474,7 @@ | |
566 | err_unlock: | |
567 | STRUCT_UNLOCK(&structure_guard_mutex); | |
568 | err: | |
569 | + thd->query_plan_flags|= QPLAN_QC_NO; | |
570 | DBUG_RETURN(0); // Query was not cached | |
571 | } | |
572 | ||
573 | diff -r 0b1f42e1aacf sql/sql_class.h | |
574 | --- a/sql/sql_class.h Thu Dec 04 08:55:22 2008 -0800 | |
575 | +++ b/sql/sql_class.h Thu Dec 04 08:55:29 2008 -0800 | |
576 | @@ -396,6 +396,11 @@ | |
577 | DATE_TIME_FORMAT *datetime_format; | |
578 | DATE_TIME_FORMAT *time_format; | |
579 | my_bool sysdate_is_now; | |
580 | + | |
581 | + ulong log_slow_rate_limit; | |
582 | + ulong log_slow_filter; | |
583 | + ulong log_slow_verbosity; | |
584 | + | |
585 | }; | |
586 | ||
587 | ||
588 | @@ -1339,6 +1344,11 @@ | |
589 | ||
590 | thr_lock_type update_lock_default; | |
591 | Delayed_insert *di; | |
592 | + | |
593 | + bool write_to_slow_log; | |
594 | + | |
595 | + ulong query_plan_flags; | |
596 | + ulong query_plan_fsort_passes; | |
597 | ||
598 | /* <> 0 if we are inside of trigger or stored function. */ | |
599 | uint in_sub_stmt; | |
600 | diff -r 0b1f42e1aacf sql/sql_connect.cc | |
601 | --- a/sql/sql_connect.cc Thu Dec 04 08:55:22 2008 -0800 | |
602 | +++ b/sql/sql_connect.cc Thu Dec 04 08:55:29 2008 -0800 | |
603 | @@ -1124,6 +1124,15 @@ | |
604 | ||
605 | prepare_new_connection_state(thd); | |
606 | ||
607 | + /* | |
608 | + If rate limiting of slow log writes is enabled, decide whether to log this | |
609 | + new thread's queries or not. Uses extremely simple algorithm. :) | |
610 | + */ | |
611 | + thd->write_to_slow_log= FALSE; | |
612 | + if (thd->variables.log_slow_rate_limit <= 1 || | |
613 | + (thd->thread_id % thd->variables.log_slow_rate_limit) == 0) | |
614 | + thd->write_to_slow_log= TRUE; | |
615 | + | |
616 | while (!net->error && net->vio != 0 && | |
617 | !(thd->killed == THD::KILL_CONNECTION)) | |
618 | { | |
619 | diff -r 0b1f42e1aacf sql/sql_parse.cc | |
620 | --- a/sql/sql_parse.cc Thu Dec 04 08:55:22 2008 -0800 | |
621 | +++ b/sql/sql_parse.cc Thu Dec 04 08:55:29 2008 -0800 | |
622 | @@ -1692,6 +1692,27 @@ | |
623 | if (unlikely(thd->in_sub_stmt)) | |
624 | DBUG_VOID_RETURN; // Don't set time for sub stmt | |
625 | ||
626 | + /* Follow the slow log filter configuration. */ | |
627 | + if (thd->variables.log_slow_filter != SLOG_F_NONE && | |
628 | + (!(thd->variables.log_slow_filter & thd->query_plan_flags) || | |
629 | + ((thd->variables.log_slow_filter & SLOG_F_QC_NO) && | |
630 | + (thd->query_plan_flags & QPLAN_QC)))) | |
631 | + DBUG_VOID_RETURN; | |
632 | + | |
633 | + /* | |
634 | + Low long_query_time value most likely means user is debugging stuff and even | |
635 | + though some thread's queries are not supposed to be logged b/c of the rate | |
636 | + limit, if one of them takes long enough (>= 1 second) it will be sensible | |
637 | + to make an exception and write to slow log anyway. | |
638 | + */ | |
639 | + if (thd->write_to_slow_log != TRUE && thd->variables.long_query_time < 1000000 && | |
640 | + (ulong) (thd->start_utime - thd->utime_after_lock) >= 1000000) | |
641 | + thd->write_to_slow_log= TRUE; | |
642 | + | |
643 | + /* Do not log this thread's queries due to rate limiting. */ | |
644 | + if (thd->write_to_slow_log != TRUE) | |
645 | + DBUG_VOID_RETURN; | |
646 | + | |
647 | /* | |
648 | Do not log administrative statements unless the appropriate option is | |
649 | set; do not log into slow log if reading from backup. | |
650 | @@ -5773,6 +5794,9 @@ | |
651 | thd->total_warn_count=0; // Warnings for this query | |
652 | thd->rand_used= 0; | |
653 | thd->sent_row_count= thd->examined_row_count= 0; | |
654 | + | |
655 | + thd->query_plan_flags= QPLAN_NONE; | |
656 | + thd->query_plan_fsort_passes= 0; | |
657 | ||
658 | /* | |
659 | Because we come here only for start of top-statements, binlog format is | |
660 | diff -r 0b1f42e1aacf sql/sql_select.cc | |
661 | --- a/sql/sql_select.cc Thu Dec 04 08:55:22 2008 -0800 | |
662 | +++ b/sql/sql_select.cc Thu Dec 04 08:55:29 2008 -0800 | |
663 | @@ -6480,7 +6480,10 @@ | |
664 | { | |
665 | join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED; | |
666 | if (statistics) | |
667 | + { | |
668 | status_var_increment(join->thd->status_var.select_scan_count); | |
669 | + join->thd->query_plan_flags|= QPLAN_FULL_SCAN; | |
670 | + } | |
671 | } | |
672 | } | |
673 | else | |
674 | @@ -6494,7 +6497,10 @@ | |
675 | { | |
676 | join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED; | |
677 | if (statistics) | |
678 | + { | |
679 | status_var_increment(join->thd->status_var.select_full_join_count); | |
680 | + join->thd->query_plan_flags|= QPLAN_FULL_JOIN; | |
681 | + } | |
682 | } | |
683 | } | |
684 | if (!table->no_keyread) | |
685 | @@ -9638,6 +9644,7 @@ | |
686 | (ulong) rows_limit,test(group))); | |
687 | ||
688 | status_var_increment(thd->status_var.created_tmp_tables); | |
689 | + thd->query_plan_flags|= QPLAN_TMP_TABLE; | |
690 | ||
691 | if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES)) | |
692 | temp_pool_slot = bitmap_lock_set_next(&temp_pool); | |
693 | @@ -10508,6 +10515,7 @@ | |
694 | goto err; | |
695 | } | |
696 | status_var_increment(table->in_use->status_var.created_tmp_disk_tables); | |
697 | + table->in_use->query_plan_flags|= QPLAN_TMP_DISK; | |
698 | share->db_record_offset= 1; | |
699 | DBUG_RETURN(0); | |
700 | err: |