From cd3047fc89fec8821dd6fcd931897468dfc1ee19 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Thu, 3 Sep 2009 17:05:38 +0300 Subject: Updated documentation files to reflect MariaDB and not the Maria storage engine or MySQL Added (rewritten) patch from Percona to get extended statistics in slow.log: - Added handling of 'set' variables to set_var.cc. Changed sql_mode to use this - Added extra logging to slow log of 'Thread_id, Schema, Query Cache hit, Rows sent and Rows examined' - Added optional logging to slow log, through log_slow_verbosity, of query plan statistics - Added new user variables log_slow_rate_limit, log_slow_verbosity, log_slow_filter - Added log-slow-file as synonym for 'slow-log-file', as most slow-log variables starts with 'log-slow' - Added log-slow-time as synonym for long-query-time Some trivial MyISAM optimizations: - In prepare for drop, flush key blocks - Don't call mi_lock_database if my_disable_locking is used KNOWN_BUGS.txt: Updated file to reflect MariaDB and not the Maria storage engine README: Updated file to reflect MariaDB mysql-test/r/log_slow.result: Test new options for slow query log mysql-test/r/variables.result: Updated result (old version cut of things at 79 characters) mysql-test/t/log_slow.test: Test new options for slow query log sql/Makefile.am: Added log_slow.h sql/event_data_objects.cc: Removed not needed test for enable_slow_log (is done when the flag is tested elsewhere) sql/events.cc: Use the general make_set() function instead of 'symbolic_mode_representation' sql/filesort.cc: Added status for used query plans sql/log.cc: Reset counters if no query_length (from Percona's patch; Not sure if needed, but can do no harm) Added extra logging to slow log of 'Thread_id, Schema, Query Cache hit, Rows sent and Rows examined' Added optional logging to slow log, through log_slow_verbosity, of query plan statistics Fixed wrong test of error condition sql/log_slow.h: Defines and variables for log_slow_verbosity and log_slow_filter sql/mysql_priv.h: Include log_slow.h sql/mysqld.cc: Added new user variables log_slow_rate_limit, log_slow_verbosity, log_slow_filter Added log-slow-file as synonym for 'slow-log-file', as most slow-log variables starts with 'log-slow' Added log-slow-time as synonym for long-query-time Added note that one should use log-slow-filter instead of log-slow-admin-statements Updated comment from 'slow_query_log_file' sql/set_var.cc: Added long_slow_time as synonym for long_query_time Added new user variables log_slow_rate_limit, log_slow_verbosity, log_slow_filter dded handling of 'set' variables to set_var.cc. Changed sql_mode to use this sql/set_var.h: - Added handling of 'set' variables. Changed sql_mode to use this sql/slave.cc: Use global filter also for slaves sql/sp_head.cc: Simplify saving of general_slow_log state Use the general make_set() function instead of 'symbolic_mode_representation' sql/sql_cache.cc: Added status for used query plans sql/sql_class.cc: Remember/restore query_plan_flags over complex statements sql/sql_class.h: Added variables to handle extended slow log statistics sql/sql_parse.cc: Added status for used query plans Added test for filtering slow_query_log sql/sql_select.cc: Added status for used query plans sql/sql_show.cc: Use the general make_set() function instead of 'symbolic_mode_representation' sql/strfunc.cc: Report first error (not last) if something is wrong in a set Removed compiler warning storage/myisam/mi_extra.c: In prepare for drop, flush key blocks (speed optimization) storage/myisam/mi_locking.c: Don't call mi_lock_database if my_disable_locking is used (speed optimization) --- KNOWN_BUGS.txt | 89 +++++------------------ README | 41 ++++++----- mysql-test/r/log_slow.result | 60 ++++++++++++++++ mysql-test/r/variables.result | 2 +- mysql-test/t/log_slow.test | 42 +++++++++++ sql/Makefile.am | 2 +- sql/event_data_objects.cc | 3 +- sql/events.cc | 3 +- sql/filesort.cc | 3 + sql/log.cc | 41 +++++++++-- sql/log_slow.h | 107 +++++++++++++++++++++++++++ sql/mysql_priv.h | 1 + sql/mysqld.cc | 58 +++++++++++++-- sql/set_var.cc | 164 +++++++++++++++++++++++++----------------- sql/set_var.h | 36 ++++++---- sql/slave.cc | 1 + sql/sp_head.cc | 12 ++-- sql/sql_cache.cc | 5 ++ sql/sql_class.cc | 2 + sql/sql_class.h | 7 ++ sql/sql_parse.cc | 25 +++++++ sql/sql_select.cc | 8 +++ sql/sql_show.cc | 10 +-- sql/strfunc.cc | 17 +++-- storage/myisam/mi_extra.c | 7 +- storage/myisam/mi_locking.c | 4 +- 26 files changed, 546 insertions(+), 204 deletions(-) create mode 100644 mysql-test/r/log_slow.result create mode 100644 mysql-test/t/log_slow.test create mode 100644 sql/log_slow.h diff --git a/KNOWN_BUGS.txt b/KNOWN_BUGS.txt index 189c7dcd613..38472fc978c 100644 --- a/KNOWN_BUGS.txt +++ b/KNOWN_BUGS.txt @@ -1,86 +1,35 @@ -This file should contain all know fatal bugs in the Maria storage -engine for the last source or binary release. Minor bugs, extensions -and feature request and bugs found since this release can be find in the -MySQL bugs databases at: http://bugs.mysql.com/ (category "Maria -storage engine"). +This file should contain all know fatal bugs in the Mariadb and the +Maria storage engine for the last source or binary release. Minor +bugs, extensions and feature request and bugs found since this release +can be find in the MariaDB bugs database at: +https://bugs.launchpad.net/maria and in the MySQL bugs databases at: +http://bugs.mysql.com/ (category "Maria storage engine"). There shouldn't normally be any bugs that affects normal operations in -any Maria release. Still, there are always exceptions and edge cases +any MariaDB release. Still, there are always exceptions and edge cases and that's what this file is for. -For the first few Alpha releases of Maria there may be some edge cases -that crashes during recovery; We don't like that but we think it's -better to get the Maria alpha out early to get things tested and get -more developers on the code early than wait until these are fixed. We -do however think that the bugs are not seriously enough to stop anyone -from starting to test and even use Maria for real (as long as they are -prepared to upgrade to next MySQL-Maria release ASAP). - If you have found a bug that is not listed here, please add it to -http://bugs.mysql.com/ so that we can either fix it for next release -or in the worst case add it here for others to know! +http://bugs.launchpad.net/maria so that we can either fix it for next +release or in the worst case add it here for others to know! IMPORTANT: -If you have been using a MySQL-5.1-Maria-alpha build and upgrading to -MySQL-5.1-Maria-beta you MUST run maria_chk --recover on all your -Maria tables. This is because we made an incompatible change of how -transaction id is stored and old transaction id's must be reset! +If you have been using the Maria storage engine with +MySQL-5.1-Maria-alpha build and upgrading to a newer MariaDB you MUST +run maria_chk --recover on all your Maria tables. This is because we +made an incompatible change of how transaction id is stored and old +transaction id's must be reset! cd mysql-data-directory maria_chk --recover */*.MAI -As the Maria-1.5 engine is now in beta we will do our best to not +As the Maria storage engine is now in beta we will do our best to not introduce any incompatible changes in the data format for the Maria tables; If this would be ever be needed, we will, if possible, support both the old and the new version to make upgrades as easy as possible. -Known bugs that we are working on and will be fixed shortly -=========================================================== - -- We have some time ago some instabilities in log writing that is was - under investigation but we haven't been able to repeat in a while. - This causes mainly assert to triggers in the code and sometimes - the log handler doesn't start up after restart. - Most of this should now be fixed. - -- INSERT on a duplicate key against a key inserted by another connection - that has not yet ended will give a duplicate key error instead of - waiting for the other statement to end. - - -Known bugs that are planned to be fixed before Gamma/RC -======================================================= - -- If we get a write failure on disk (disk full or disk error) for the - log, we should stop all usage of transactional tables and mark all - transactional tables that are changed as crashed. - For the moment, if this happens, you have to take down mysqld, - remove all logs, restart mysqld and repair your tables. - - If you get the related error: - "Disk is full writing '/usr/local/mysql/var/maria_log.????????' (Errcode: 28) - Waiting for someone to free space..." - you should either free disk space, in which Maria will continue as before - or kill mysqld, remove logs and repair tables. - - -Known bugs that are planned to be fixed later -============================================= - -LOCK TABLES .. WRITE CONCURRENT is mainly done for testing MVCC. Don't -use this in production. - -Missing features that is planned to fix before Beta -=================================================== - -None - -Features planned for future releases -==================================== - -Most notable is full transaction support and multiple reader/writers -in Maria 2.0 - -http://forge.mysql.com/worklog/ -(you can enter "maria" in the "quick search" field there). +Note that for the MariaDB 5.1 release the Maria storage engine is +classified as 'beta'; It should work, but use it with caution. Please +report all bugs to https://bugs.launchpad.net/maria so that we can fix +them! diff --git a/README b/README index 56bd912d3d6..33ff023b5aa 100644 --- a/README +++ b/README @@ -1,35 +1,44 @@ -This is a release of MySQL, a dual-license SQL database server. -MySQL is brought to you by the MySQL team at MySQL AB. +This is a release of MariaDB, a branch of MySQL. + +MariaDB is a drop-in replacement of MySQL, with more features, less +bugs and better performance. + +MariaDB is brought to you by many of the original developers of MySQL, +that now work for Monty Program Ab, and by many people in the +community. + +MySQL, which is the base of MariaDB, is brought to you by Sun. License information can be found in these files: - For GPL (free) distributions, see the COPYING file and the EXCEPTIONS-CLIENT file. -- For commercial distributions, see the LICENSE.mysql file. +A description of the MariaDB project can be found at: +http://askmonty.org/wiki/index.php/MariaDB + +The differences between MariaDB and MySQL can be found at: +http://askmonty.org/wiki/index.php/MariaDB_versus_MySQL + +Documentation about MySQL can be found at: +http://dev.mysql.com/doc -For further information about MySQL or additional documentation, see: -- The latest information about MySQL: http://www.mysql.com -- The current MySQL documentation: http://dev.mysql.com/doc +For further information about MySQL documentation, see: +- The current MySQL documentation: Some manual sections of special interest: -- If you are migrating from an older version of MySQL, please read the - "Upgrading from..." section first! -- To see what MySQL can do, take a look at the features section. -- For installation instructions, see the Installing and Upgrading chapter. -- For the new features/bugfix history, see the Change History appendix. -- For the currently known bugs/misfeatures (known errors) see the Problems - and Common Errors appendix. - For a list of developers and other contributors, see the Credits appendix. A local copy of the MySQL Reference Manual can be found in the Docs directory in GNU Info format. You can also browse the manual online or -download it in any of several formats at the URL given earlier in this -file. +download it in any of several formats from +http://dev.mysql.com/doc ************************************************************ IMPORTANT: -Bug or error reports should be sent to http://bugs.mysql.com. +Bug or error reports regarding MariaDB should be sent to +https://bugs.launchpad.net/maria +Bugs in the MySQL code can also be sent to http://bugs.mysql.com diff --git a/mysql-test/r/log_slow.result b/mysql-test/r/log_slow.result new file mode 100644 index 00000000000..57d12a64f5a --- /dev/null +++ b/mysql-test/r/log_slow.result @@ -0,0 +1,60 @@ +select @@log_slow_filter; +@@log_slow_filter + +select @@log_slow_rate_limit; +@@log_slow_rate_limit +1 +select @@log_slow_verbosity; +@@log_slow_verbosity + +show variables like "log_slow%"; +Variable_name Value +log_slow_filter +log_slow_queries ON +log_slow_rate_limit 1 +log_slow_time 10.000000 +log_slow_verbosity +set @@log_slow_filter= "filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk,admin"; +select @@log_slow_filter; +@@log_slow_filter +admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk +set @@log_slow_filter="admin,admin"; +select @@log_slow_filter; +@@log_slow_filter +admin +set @@log_slow_filter=7; +select @@log_slow_filter; +@@log_slow_filter +admin,filesort,filesort_on_disk +set @@log_slow_filter= "filesort,impossible,impossible2,admin"; +ERROR 42000: Variable 'log_slow_filter' can't be set to the value of 'impossible' +set @@log_slow_filter= "filesort, admin"; +ERROR 42000: Variable 'log_slow_filter' can't be set to the value of ' admin' +set @@log_slow_filter= 1<<31; +ERROR 42000: Variable 'log_slow_filter' can't be set to the value of '2147483648' +select @@log_slow_filter; +@@log_slow_filter +admin,filesort,filesort_on_disk +set @@log_slow_verbosity= "query_plan,innodb"; +select @@log_slow_verbosity; +@@log_slow_verbosity +innodb,query_plan +set @@log_slow_verbosity=1; +select @@log_slow_verbosity; +@@log_slow_verbosity +innodb +show fields from mysql.slow_log; +Field Type Null Key Default Extra +start_time timestamp NO CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP +user_host mediumtext NO NULL +query_time time NO NULL +lock_time time NO NULL +rows_sent int(11) NO NULL +rows_examined int(11) NO NULL +db varchar(512) NO NULL +last_insert_id int(11) NO NULL +insert_id int(11) NO NULL +server_id int(10) unsigned NO NULL +sql_text mediumtext NO NULL +set @@log_slow_filter=default; +set @@log_slow_verbosity=default; diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index db6479615c9..822cd5ac04f 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -865,7 +865,7 @@ select @@query_prealloc_size = @test; @@query_prealloc_size = @test 1 set global sql_mode=repeat('a',80); -ERROR 42000: Variable 'sql_mode' can't be set to the value of 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' +ERROR 42000: Variable 'sql_mode' can't be set to the value of 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' End of 4.1 tests create table t1 (a int); select a into @x from t1; diff --git a/mysql-test/t/log_slow.test b/mysql-test/t/log_slow.test new file mode 100644 index 00000000000..303d5bf8deb --- /dev/null +++ b/mysql-test/t/log_slow.test @@ -0,0 +1,42 @@ +# +# Testing of slow log query options +# + +select @@log_slow_filter; +select @@log_slow_rate_limit; +select @@log_slow_verbosity; +show variables like "log_slow%"; + +# Some simple test to set log_slow_filter +set @@log_slow_filter= "filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk,admin"; +select @@log_slow_filter; +set @@log_slow_filter="admin,admin"; +select @@log_slow_filter; +set @@log_slow_filter=7; +select @@log_slow_filter; + +# Test of wrong values +--error 1231 +set @@log_slow_filter= "filesort,impossible,impossible2,admin"; +--error 1231 +set @@log_slow_filter= "filesort, admin"; +--error 1231 +set @@log_slow_filter= 1<<31; +select @@log_slow_filter; + +# Some simple test to set log_slow_verbosity +set @@log_slow_verbosity= "query_plan,innodb"; +select @@log_slow_verbosity; +set @@log_slow_verbosity=1; +select @@log_slow_verbosity; + +# +# Check which fields are in slow_log table +# + +show fields from mysql.slow_log; + +# Reset used variables + +set @@log_slow_filter=default; +set @@log_slow_verbosity=default; diff --git a/sql/Makefile.am b/sql/Makefile.am index a3559b38ce4..2bee2c12810 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -61,7 +61,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ ha_partition.h rpl_constants.h \ opt_range.h protocol.h rpl_tblmap.h rpl_utility.h \ rpl_reporting.h \ - log.h sql_show.h rpl_rli.h rpl_mi.h \ + log.h log_slow.h sql_show.h rpl_rli.h rpl_mi.h \ sql_select.h structs.h table.h sql_udf.h hash_filo.h \ lex.h lex_symbol.h sql_acl.h sql_crypt.h \ sql_repl.h slave.h rpl_filter.h rpl_injector.h \ diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index fdc18954c55..721279fb77c 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -1456,8 +1456,7 @@ Event_job_data::execute(THD *thd, bool drop) DBUG_ASSERT(sphead); - if (thd->enable_slow_log) - sphead->m_flags|= sp_head::LOG_SLOW_STATEMENTS; + sphead->m_flags|= sp_head::LOG_SLOW_STATEMENTS; sphead->m_flags|= sp_head::LOG_GENERAL_LOG; sphead->set_info(0, 0, &thd->lex->sp_chistics, sql_mode); diff --git a/sql/events.cc b/sql/events.cc index e1b4dd4d513..968e86c427b 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -689,8 +689,7 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol) field_list.push_back(new Item_empty_string("Event", NAME_CHAR_LEN)); - if (sys_var_thd_sql_mode::symbolic_mode_representation(thd, et->sql_mode, - &sql_mode)) + if (sys_var::make_set(thd, et->sql_mode, &sql_mode_typelib, &sql_mode)) DBUG_RETURN(TRUE); field_list.push_back(new Item_empty_string("sql_mode", (uint) sql_mode.length)); diff --git a/sql/filesort.cc b/sql/filesort.cc index f5fe17e6ff1..552ea27970f 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -188,6 +188,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, { status_var_increment(thd->status_var.filesort_scan_count); } + thd->query_plan_flags|= QPLAN_FILESORT; #ifdef CAN_TRUST_RANGE if (select && select->quick && select->quick->records > 0L) { @@ -253,6 +254,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, } else { + thd->query_plan_flags|= QPLAN_FILESORT_DISK; if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer) { x_free(table_sort.buffpek); @@ -1199,6 +1201,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, DBUG_ENTER("merge_buffers"); status_var_increment(current_thd->status_var.filesort_merge_passes); + current_thd->query_plan_fsort_passes++; if (param->not_killable) { killed= ¬_killable; diff --git a/sql/log.cc b/sql/log.cc index a86bbac873a..5b79ade261f 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -964,7 +964,7 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length, /* fill in user_host value: the format is "%s[%s] @ %s [%s]" */ user_host_len= (strxnmov(user_host_buff, MAX_USER_HOST_SIZE, sctx->priv_user ? sctx->priv_user : "", "[", - sctx->user ? sctx->user : "", "] @ ", + sctx->user ? sctx->user : (thd->slave_thread ? "SQL_SLAVE" : ""), "] @ ", sctx->host ? sctx->host : "", " [", sctx->ip ? sctx->ip : "", "]", NullS) - user_host_buff); @@ -987,6 +987,17 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length, query_length= command_name[thd->command].length; } + if (!query_length) + { + /* + Not a real query; Reset counts for slow query logging + (QQ: Wonder if this is really needed) + */ + thd->sent_row_count= thd->examined_row_count= 0; + thd->query_plan_flags= QPLAN_INIT; + thd->query_plan_fsort_passes= 0; + } + for (current_handler= slow_log_handler_list; *current_handler ;) error= (*current_handler++)->log_slow(thd, current_time, thd->start_time, user_host_buff, user_host_len, @@ -2202,19 +2213,39 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, if (my_b_write(&log_file, (uchar*) "\n", 1)) tmp_errno= errno; } + /* For slow query log */ sprintf(query_time_buff, "%.6f", ulonglong2double(query_utime)/1000000.0); sprintf(lock_time_buff, "%.6f", ulonglong2double(lock_utime)/1000000.0); if (my_b_printf(&log_file, - "# Query_time: %s Lock_time: %s" - " Rows_sent: %lu Rows_examined: %lu\n", + "# Thread_id: %lu Schema: %s QC_hit: %s\n" \ + "# Query_time: %s Lock_time: %s Rows_sent: %lu Rows_examined: %lu\n", + (ulong) thd->thread_id, (thd->db ? thd->db : ""), + ((thd->query_plan_flags & QPLAN_QC) ? "Yes" : "No"), query_time_buff, lock_time_buff, (ulong) thd->sent_row_count, - (ulong) thd->examined_row_count) == (uint) -1) + (ulong) thd->examined_row_count) == (size_t) -1) tmp_errno= errno; + if ((thd->variables.log_slow_verbosity & LOG_SLOW_VERBOSITY_QUERY_PLAN) && + (thd->query_plan_flags & + (QPLAN_FULL_SCAN | QPLAN_FULL_JOIN | QPLAN_TMP_TABLE | + QPLAN_TMP_DISK | QPLAN_FILESORT | QPLAN_FILESORT_DISK)) && + my_b_printf(&log_file, + "# Full_scan: %s Full_join: %s " + "Tmp_table: %s Tmp_table_on_disk: %s\n" + "# Filesort: %s Filesort_on_disk: %s Merge_passes: %lu\n", + ((thd->query_plan_flags & QPLAN_FULL_SCAN) ? "Yes" : "No"), + ((thd->query_plan_flags & QPLAN_FULL_JOIN) ? "Yes" : "No"), + ((thd->query_plan_flags & QPLAN_TMP_TABLE) ? "Yes" : "No"), + ((thd->query_plan_flags & QPLAN_TMP_DISK) ? "Yes" : "No"), + ((thd->query_plan_flags & QPLAN_FILESORT) ? "Yes" : "No"), + ((thd->query_plan_flags & QPLAN_FILESORT_DISK) ? + "Yes" : "No"), + thd->query_plan_fsort_passes) == (size_t) -1) + tmp_errno= errno; if (thd->db && strcmp(thd->db, db)) { // Database changed - if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1) + if (my_b_printf(&log_file,"use %s;\n",thd->db) == (size_t) -1) tmp_errno= errno; strmov(db,thd->db); } diff --git a/sql/log_slow.h b/sql/log_slow.h new file mode 100644 index 00000000000..5559c002fde --- /dev/null +++ b/sql/log_slow.h @@ -0,0 +1,107 @@ +/* Copyright (C) 2009 Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 or later of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* Defining what to log to slow log */ + +#define LOG_SLOW_VERBOSITY_INIT 0 +#define LOG_SLOW_VERBOSITY_INNODB 1 << 0 +#define LOG_SLOW_VERBOSITY_QUERY_PLAN 1 << 1 + +#ifdef DEFINE_VARIABLES_LOG_SLOW + +/* Names here must be in same order as the bit's above */ +static const char *log_slow_verbosity_names[]= +{ + "innodb","query_plan", + NullS +}; + +static const unsigned int log_slow_verbosity_names_len[]= +{ + sizeof("innodb") -1, + sizeof("query_plan")-1 +}; + +TYPELIB log_slow_verbosity_typelib= +{ array_elements(log_slow_verbosity_names)-1,"", log_slow_verbosity_names, + (unsigned int *) log_slow_verbosity_names_len }; + +#else +extern TYPELIB log_slow_verbosity_typelib; +#endif /* DEFINE_VARIABLES_LOG_SLOW */ + +/* Defines for what kind of query plan was used and what to log */ + +/* + We init the used query plan with a bit that is alwyas set and all 'no' bits + to enable easy testing of what to log in sql_log.cc +*/ +#define QPLAN_INIT (QPLAN_ALWAYS_SET | QPLAN_QC_NO) + +#define QPLAN_ADMIN 1 << 0 +#define QPLAN_FILESORT 1 << 1 +#define QPLAN_FILESORT_DISK 1 << 2 +#define QPLAN_FULL_JOIN 1 << 3 +#define QPLAN_FULL_SCAN 1 << 4 +#define QPLAN_QC 1 << 5 +#define QPLAN_QC_NO 1 << 6 +#define QPLAN_TMP_DISK 1 << 7 +#define QPLAN_TMP_TABLE 1 << 8 +/* ... */ +#define QPLAN_MAX ((ulong) 1) << 31 /* reserved as placeholder */ +#define QPLAN_ALWAYS_SET QPLAN_MAX +#define QPLAN_VISIBLE_MASK (~(QPLAN_ALWAYS_SET)) + +#ifdef DEFINE_VARIABLES_LOG_SLOW +/* Names here must be in same order as the bit's above */ +static const char *log_slow_filter_names[]= +{ + "admin", + "filesort", + "filesort_on_disk", + "full_join", + "full_scan", + "query_cache", + "query_cache_miss", + "tmp_table", + "tmp_table_on_disk", + NullS +}; + +static const unsigned int log_slow_filter_names_len[]= +{ + sizeof("admin")-1, + sizeof("filesort")-1, + sizeof("filesort_on_disk")-1, + sizeof("full_join")-1, + sizeof("full_scan")-1, + sizeof("query_cache")-1, + sizeof("query_cache_miss")-1, + sizeof("tmp_table")-1, + sizeof("tmp_table_on_disk")-1 +}; + +TYPELIB log_slow_filter_typelib= +{ array_elements(log_slow_filter_names)-1,"", log_slow_filter_names, + (unsigned int *) log_slow_filter_names_len }; + +#else +extern TYPELIB log_slow_filter_typelib; +#endif /* DEFINE_VARIABLES_LOG_SLOW */ + +static inline ulong fix_log_slow_filter(ulong org_filter) +{ + return org_filter ? org_filter : QPLAN_ALWAYS_SET; +} diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 816efe05c18..9c93e4a0309 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -43,6 +43,7 @@ #include "sql_array.h" #include "sql_plugin.h" #include "scheduler.h" +#include "log_slow.h" class Parser_state; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4a5a207ca1c..7fd460f52e4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -13,6 +13,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#define DEFINE_VARIABLES_LOG_SLOW // Declare variables in log_slow.h #include "mysql_priv.h" #include #include @@ -5758,6 +5759,9 @@ enum options_mysqld OPT_DEADLOCK_SEARCH_DEPTH_LONG, OPT_DEADLOCK_TIMEOUT_SHORT, OPT_DEADLOCK_TIMEOUT_LONG, + OPT_LOG_SLOW_RATE_LIMIT, + OPT_LOG_SLOW_VERBOSITY, + OPT_LOG_SLOW_FILTER, OPT_GENERAL_LOG_FILE, OPT_SLOW_QUERY_LOG_FILE, OPT_IGNORE_BUILTIN_INNODB @@ -6100,7 +6104,7 @@ Disable with --skip-large-pages.", (uchar**) &opt_log_slave_updates, (uchar**) &opt_log_slave_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-slow-admin-statements", OPT_LOG_SLOW_ADMIN_STATEMENTS, - "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to the slow log if it is open.", + "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to the slow log if it is open. . Please note that this option is deprecated; see --log-slow-filter for filtering slow query log output", (uchar**) &opt_log_slow_admin_statements, (uchar**) &opt_log_slow_admin_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -6109,15 +6113,15 @@ Disable with --skip-large-pages.", (uchar**) &opt_log_slow_slave_statements, (uchar**) &opt_log_slow_slave_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"log_slow_queries", OPT_SLOW_QUERY_LOG, + {"log-slow-queries", OPT_SLOW_QUERY_LOG, "Log slow queries to a table or log file. Defaults logging to table " "mysql.slow_log or hostname-slow.log if --log-output=file is used. " "Must be enabled to activate other slow log options. " "(deprecated option, use --slow_query_log/--slow_query_log_file instead)", (uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"slow_query_log_file", OPT_SLOW_QUERY_LOG_FILE, - "Log slow queries to given log file. Defaults logging to hostname-slow.log. Must be enabled to activate other slow log options.", + {"slow-query-log-file", OPT_SLOW_QUERY_LOG_FILE, + "Log slow queries to given log file. Defaults logging to hostname-slow.log.", (uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"log-tc", OPT_LOG_TC, @@ -6737,11 +6741,31 @@ log and this option does nothing anymore.", (uchar**) 0, 0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100, 1, 100, 0, 1, 0}, + {"log-slow-filter", OPT_LOG_SLOW_FILTER, + "Log only the queries that followed certain execution plan. Multiple flags allowed in a comma-separated string. [admin, filesort, filesort_on_disk, full_join, full_scan, query_cache, query_cache_miss, tmp_table, tmp_table_on_disk]. Sets log-slow-admin-command to ON", + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, QPLAN_ALWAYS_SET, 0, 0}, + {"log-slow-rate_limit", OPT_LOG_SLOW_RATE_LIMIT, + "If set, only write to slow log every 'log_slow_rate_limit' query (use this to reduce output on slow query log)", + (uchar**) &global_system_variables.log_slow_rate_limit, + (uchar**) &max_system_variables.log_slow_rate_limit, 0, GET_ULONG, + REQUIRED_ARG, 1, 1, ~0L, 0, 1L, 0}, + {"log-slow-verbosity", OPT_LOG_SLOW_VERBOSITY, + "Choose how verbose the messages to your slow log will be. Multiple flags allowed in a comma-separated string. [query_plan, innodb]", + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + {"log-slow-file", OPT_SLOW_QUERY_LOG_FILE, + "Log slow queries to given log file. Defaults logging to hostname-slow.log", + (uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR, + REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"long_query_time", OPT_LONG_QUERY_TIME, "Log all queries that have taken more than long_query_time seconds to execute to file. " "The argument will be treated as a decimal value with microsecond precission.", (uchar**) &long_query_time, (uchar**) &long_query_time, 0, GET_DOUBLE, REQUIRED_ARG, 10, 0, LONG_TIMEOUT, 0, 0, 0}, + {"log-slow-time", OPT_LONG_QUERY_TIME, + "Log all queries that have taken more than long_query_time seconds to execute to file. " + "The argument will be treated as a decimal value with microsecond precission.", + (uchar**) &long_query_time, (uchar**) &long_query_time, 0, GET_DOUBLE, + REQUIRED_ARG, 10, 0, LONG_TIMEOUT, 0, 0, 0}, {"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES, "If set to 1 table names are stored in lowercase on disk and table names will be case-insensitive. Should be set to 2 if you are using a case insensitive file system", (uchar**) &lower_case_table_names, @@ -7843,6 +7867,9 @@ static int mysql_init_variables(void) global_system_variables.old_passwords= 0; global_system_variables.old_alter_table= 0; global_system_variables.binlog_format= BINLOG_FORMAT_UNSPEC; + global_system_variables.log_slow_verbosity= LOG_SLOW_VERBOSITY_INIT; + global_system_variables.log_slow_filter= QPLAN_ALWAYS_SET; + /* Default behavior for 4.1 and 5.0 is to treat NULL values as unequal when collecting index statistics for MyISAM tables. @@ -8197,7 +8224,7 @@ mysqld_get_one_option(int optid, } #endif /* HAVE_REPLICATION */ case (int) OPT_SLOW_QUERY_LOG: - WARN_DEPRECATED(NULL, "7.0", "--log_slow_queries", "'--slow_query_log'/'--slow_query_log_file'"); + WARN_DEPRECATED(NULL, "7.0", "--log_slow_queries", "'--slow_query_log'/'--log-slow-file'"); opt_slow_log= 1; break; #ifdef WITH_CSV_STORAGE_ENGINE @@ -8350,6 +8377,25 @@ mysqld_get_one_option(int optid, case OPT_BOOTSTRAP: opt_noacl=opt_bootstrap=1; break; + case OPT_LOG_SLOW_FILTER: + global_system_variables.log_slow_filter= + find_bit_type_or_exit(argument, &log_slow_verbosity_typelib, + opt->name, &error); + /* + If we are using filters, we set opt_slow_admin_statements to be always + true so we can maintain everything with filters + */ + opt_log_slow_admin_statements= 1; + if (error) + return 1; + break; + case OPT_LOG_SLOW_VERBOSITY: + global_system_variables.log_slow_verbosity= + find_bit_type_or_exit(argument, &log_slow_filter_typelib, + opt->name, &error); + if (error) + return 1; + break; case OPT_SERVER_ID: server_id_supplied = 1; break; @@ -8658,6 +8704,8 @@ static int get_options(int *argc,char **argv) /* Set global slave_exec_mode from its option */ fix_slave_exec_mode(OPT_GLOBAL); + global_system_variables.log_slow_filter= + fix_log_slow_filter(global_system_variables.log_slow_filter); #ifndef EMBEDDED_LIBRARY if (mysqld_chroot) set_root(mysqld_chroot); diff --git a/sql/set_var.cc b/sql/set_var.cc index 395725a3afc..3b3dad8a486 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -147,6 +147,7 @@ static bool sys_update_general_log_path(THD *thd, set_var * var); static void sys_default_general_log_path(THD *thd, enum_var_type type); static bool sys_update_slow_log_path(THD *thd, set_var * var); static void sys_default_slow_log_path(THD *thd, enum_var_type type); +static void fix_sys_log_slow_filter(THD *thd, enum_var_type); /* Variable definition list @@ -359,6 +360,9 @@ static sys_var_bool_ptr static sys_var_thd_ulong sys_log_warnings(&vars, "log_warnings", &SV::log_warnings); static sys_var_microseconds sys_var_long_query_time(&vars, "long_query_time", &SV::long_query_time); +static sys_var_microseconds sys_var_long_query_time2(&vars, + "log_slow_time", + &SV::long_query_time); static sys_var_thd_bool sys_low_priority_updates(&vars, "low_priority_updates", &SV::low_priority_updates, fix_low_priority_updates); @@ -852,6 +856,20 @@ sys_var_thd_ulong sys_group_concat_max_len(&vars, "group_concat_ma sys_var_thd_time_zone sys_time_zone(&vars, "time_zone", sys_var::SESSION_VARIABLE_IN_BINLOG); +/* Unique variables for MariaDB */ +static sys_var_thd_ulong sys_log_slow_rate_limit(&vars, + "log_slow_rate_limit", + &SV::log_slow_rate_limit); +static sys_var_thd_set sys_log_slow_filter(&vars, "log_slow_filter", + &SV::log_slow_filter, + &log_slow_filter_typelib, + QPLAN_VISIBLE_MASK, + fix_sys_log_slow_filter); +static sys_var_thd_set sys_log_slow_verbosity(&vars, + "log_slow_verbosity", + &SV::log_slow_verbosity, + &log_slow_verbosity_typelib); + /* Global read-only variable containing hostname */ static sys_var_const_str sys_hostname(&vars, "hostname", glob_hostname); @@ -1850,11 +1868,17 @@ err: return 1; } +/** + Check vality of set + + Note that this sets 'save_result.ulong_value' for the update function, + which means that we don't need a separate sys_var::update() function +*/ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names) { bool not_used; - char buff[STRING_BUFFER_USUAL_SIZE], *error= 0; + char buff[256], *error= 0; uint error_len= 0; String str(buff, sizeof(buff) - 1, system_charset_info), *res; @@ -1866,8 +1890,7 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names) goto err; } - if (!m_allow_empty_value && - res->length() == 0) + if (!m_allow_empty_value && res->length() == 0) { buff[0]= 0; goto err; @@ -1889,8 +1912,7 @@ bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names) { ulonglong tmp= var->value->val_int(); - if (!m_allow_empty_value && - tmp == 0) + if (!m_allow_empty_value && tmp == 0) { buff[0]= '0'; buff[1]= 0; @@ -1917,6 +1939,49 @@ err: } +/** + Make string representation of set + + @param[in] thd thread handler + @param[in] val sql_mode value + @param[in] names names for the different bits + @param[out] rep Result string + + @return + 0 ok + 1 end of memory +*/ + +bool sys_var::make_set(THD *thd, ulonglong val, TYPELIB *names, + LEX_STRING *rep) +{ + /* Strings for typelib may be big; This is reallocated on demand */ + char buff[256]; + String tmp(buff, sizeof(buff) - 1, &my_charset_latin1); + bool error= 0; + + tmp.length(0); + for (uint i= 0; val; val>>= 1, i++) + { + if (val & 1) + { + error|= tmp.append(names->type_names[i], + names->type_lengths[i]); + error|= tmp.append(','); + } + } + + if (tmp.length()) + tmp.length(tmp.length() - 1); /* trim the trailing comma */ + + /* Allocate temporary copy of string */ + if (!(rep->str= thd->strmake(tmp.ptr(), tmp.length()))) + error= 1; + rep->length= tmp.length(); + return error; /* Error in case of out of memory */ +} + + CHARSET_INFO *sys_var::charset(THD *thd) { return is_os_charset ? thd->variables.character_set_filesystem : @@ -1952,6 +2017,16 @@ uchar *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type, return (uchar*) enum_names->type_names[tmp]; } +uchar *sys_var_thd_set::value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) +{ + LEX_STRING sql_mode; + ulong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : + thd->variables.*offset); + (void) make_set(thd, val & visible_value_mask, enum_names, &sql_mode); + return (uchar *) sql_mode.str; +} + bool sys_var_thd_bit::check(THD *thd, set_var *var) { return (check_enum(thd, var, &bool_typelib) || @@ -3699,6 +3774,24 @@ int set_var_password::update(THD *thd) #endif } +/**************************************************************************** + Functions to handle log_slow_filter +****************************************************************************/ + +/* Ensure that the proper bits are set for easy test of logging */ +static void fix_sys_log_slow_filter(THD *thd, enum_var_type type) +{ + /* Maintain everything with filters */ + opt_log_slow_admin_statements= 1; + if (type == OPT_GLOBAL) + global_system_variables.log_slow_filter= + fix_log_slow_filter(global_system_variables.log_slow_filter); + else + thd->variables.log_slow_filter= + fix_log_slow_filter(thd->variables.log_slow_filter); +} + + /**************************************************************************** Functions to handle table_type ****************************************************************************/ @@ -3810,67 +3903,6 @@ bool sys_var_thd_table_type::update(THD *thd, set_var *var) Functions to handle sql_mode ****************************************************************************/ -/** - Make string representation of mode. - - @param[in] thd thread handler - @param[in] val sql_mode value - @param[out] len pointer on length of string - - @return - pointer to string with sql_mode representation -*/ - -bool -sys_var_thd_sql_mode:: -symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep) -{ - char buff[STRING_BUFFER_USUAL_SIZE*8]; - String tmp(buff, sizeof(buff) - 1, &my_charset_latin1); - - tmp.length(0); - - for (uint i= 0; val; val>>= 1, i++) - { - if (val & 1) - { - tmp.append(sql_mode_typelib.type_names[i], - sql_mode_typelib.type_lengths[i]); - tmp.append(','); - } - } - - if (tmp.length()) - tmp.length(tmp.length() - 1); /* trim the trailing comma */ - - rep->str= thd->strmake(tmp.ptr(), tmp.length()); - - rep->length= rep->str ? tmp.length() : 0; - - return rep->length != tmp.length(); -} - - -uchar *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - LEX_STRING sql_mode; - ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : - thd->variables.*offset); - (void) symbolic_mode_representation(thd, val, &sql_mode); - return (uchar *) sql_mode.str; -} - - -void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.*offset= 0; - else - thd->variables.*offset= global_system_variables.*offset; -} - - void fix_sql_mode_var(THD *thd, enum_var_type type) { if (type == OPT_GLOBAL) diff --git a/sql/set_var.h b/sql/set_var.h index 10e6e0f9c35..f2c7c0ba30f 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -98,6 +98,8 @@ public: virtual bool check(THD *thd, set_var *var); bool check_enum(THD *thd, set_var *var, const TYPELIB *enum_names); bool check_set(THD *thd, set_var *var, TYPELIB *enum_names); + static bool make_set(THD *thd, ulonglong sql_mode, TYPELIB *names, + LEX_STRING *rep); bool is_written_to_binlog(enum_var_type type) { return (type == OPT_SESSION || type == OPT_DEFAULT) && @@ -532,6 +534,25 @@ public: }; +class sys_var_thd_set :public sys_var_thd_enum +{ + ulong visible_value_mask; /* Mask away internal bits */ +public: + sys_var_thd_set(sys_var_chain *chain, const char *name_arg, + ulong SV::*offset_arg, TYPELIB *typelib, + ulong value_mask= ~ (ulong) 0, + sys_after_update_func func= NULL) + :sys_var_thd_enum(chain, name_arg, offset_arg, typelib, + func), visible_value_mask(value_mask) + {} + bool check(THD *thd, set_var *var) + { + return check_set(thd, var, enum_names); + } + uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); +}; + + class sys_var_thd_optimizer_switch :public sys_var_thd_enum { public: @@ -548,22 +569,14 @@ public: extern void fix_sql_mode_var(THD *thd, enum_var_type type); -class sys_var_thd_sql_mode :public sys_var_thd_enum +class sys_var_thd_sql_mode :public sys_var_thd_set { public: sys_var_thd_sql_mode(sys_var_chain *chain, const char *name_arg, ulong SV::*offset_arg) - :sys_var_thd_enum(chain, name_arg, offset_arg, &sql_mode_typelib, - fix_sql_mode_var) + :sys_var_thd_set(chain, name_arg, offset_arg, &sql_mode_typelib, + ~(ulong) 0, fix_sql_mode_var) {} - bool check(THD *thd, set_var *var) - { - return check_set(thd, var, enum_names); - } - void set_default(THD *thd, enum_var_type type); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - static bool symbolic_mode_representation(THD *thd, ulonglong sql_mode, - LEX_STRING *rep); }; @@ -1184,7 +1197,6 @@ public: bool update(THD *thd, set_var *var); }; - /** Handler for setting the system variable --read-only. */ diff --git a/sql/slave.cc b/sql/slave.cc index b6138078e35..d4c6049b748 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1583,6 +1583,7 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) + MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */ thd->slave_thread = 1; thd->enable_slow_log= opt_log_slow_slave_statements; + thd->variables.log_slow_filter= global_system_variables.log_slow_filter; set_slave_thread_options(thd); thd->client_capabilities = CLIENT_LOCAL_FILES; pthread_mutex_lock(&LOCK_thread_count); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index fcf51aac1b5..7fef7b30759 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1845,7 +1845,7 @@ sp_head::execute_procedure(THD *thd, List *args) uint params = m_pcont->context_var_count(); sp_rcontext *save_spcont, *octx; sp_rcontext *nctx = NULL; - bool save_enable_slow_log= false; + bool save_enable_slow_log; bool save_log_general= false; DBUG_ENTER("sp_head::execute_procedure"); DBUG_PRINT("info", ("procedure %s", m_name.str)); @@ -1956,10 +1956,10 @@ sp_head::execute_procedure(THD *thd, List *args) DBUG_PRINT("info",(" %.*s: eval args done", (int) m_name.length, m_name.str)); } - if (!(m_flags & LOG_SLOW_STATEMENTS) && thd->enable_slow_log) + save_enable_slow_log= thd->enable_slow_log; + if (!(m_flags & LOG_SLOW_STATEMENTS) && save_enable_slow_log) { DBUG_PRINT("info", ("Disabling slow log for the execution")); - save_enable_slow_log= true; thd->enable_slow_log= FALSE; } if (!(m_flags & LOG_GENERAL_LOG) && !(thd->options & OPTION_LOG_OFF)) @@ -1982,8 +1982,7 @@ sp_head::execute_procedure(THD *thd, List *args) if (save_log_general) thd->options &= ~OPTION_LOG_OFF; - if (save_enable_slow_log) - thd->enable_slow_log= true; + thd->enable_slow_log= save_enable_slow_log; /* In the case when we weren't able to employ reuse mechanism for OUT/INOUT paranmeters, we should reallocate memory. This @@ -2396,8 +2395,7 @@ sp_head::show_create_routine(THD *thd, int type) if (check_show_routine_access(thd, this, &full_access)) DBUG_RETURN(TRUE); - sys_var_thd_sql_mode::symbolic_mode_representation( - thd, m_sql_mode, &sql_mode); + sys_var::make_set(thd, m_sql_mode, &sql_mode_typelib, &sql_mode); /* Send header. */ diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index d56e246edae..c03f10c6583 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1530,6 +1530,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", thd->limit_found_rows = query->found_rows(); thd->status_var.last_query_cost= 0.0; + thd->query_plan_flags= (thd->query_plan_flags & ~QPLAN_QC_NO) | QPLAN_QC; thd->main_da.disable_status(); BLOCK_UNLOCK_RD(query_block); @@ -1538,6 +1539,10 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", err_unlock: STRUCT_UNLOCK(&structure_guard_mutex); err: + /* + query_plan_flags doesn't have to be changed here as it contains + QPLAN_QC_NO by default + */ DBUG_RETURN(0); // Query was not cached } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f0c7fc8c85d..51fd9a54e52 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -3007,6 +3007,7 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, backup->options= options; backup->in_sub_stmt= in_sub_stmt; backup->enable_slow_log= enable_slow_log; + backup->query_plan_flags= query_plan_flags; backup->limit_found_rows= limit_found_rows; backup->examined_row_count= examined_row_count; backup->sent_row_count= sent_row_count; @@ -3071,6 +3072,7 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) options= backup->options; in_sub_stmt= backup->in_sub_stmt; enable_slow_log= backup->enable_slow_log; + query_plan_flags= backup->query_plan_flags; first_successful_insert_id_in_prev_stmt= backup->first_successful_insert_id_in_prev_stmt; first_successful_insert_id_in_cur_stmt= diff --git a/sql/sql_class.h b/sql/sql_class.h index 3183699fcd0..a7235a2a755 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -349,6 +349,10 @@ struct system_variables ulong trans_prealloc_size; ulong log_warnings; ulong group_concat_max_len; + /* Flags for slow log filtering */ + ulong log_slow_rate_limit; + ulong log_slow_filter; + ulong log_slow_verbosity; ulong ndb_autoincrement_prefetch_sz; ulong ndb_index_stat_cache_entries; ulong ndb_index_stat_update_freq; @@ -995,6 +999,7 @@ public: ulonglong limit_found_rows; ha_rows cuted_fields, sent_row_count, examined_row_count; ulong client_capabilities; + ulong query_plan_flags; uint in_sub_stmt; bool enable_slow_log; bool last_insert_id_used; @@ -1696,6 +1701,8 @@ public: create_sort_index(); may differ from examined_row_count. */ ulong row_count; + ulong query_plan_flags; + ulong query_plan_fsort_passes; pthread_t real_id; /* For debugging */ my_thread_id thread_id; uint tmp_table, global_read_lock; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 54365da5496..3f2fcbac2c8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1049,6 +1049,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, status_var_increment(thd->status_var.com_other); thd->enable_slow_log= opt_log_slow_admin_statements; + thd->query_plan_flags|= QPLAN_ADMIN; db.str= (char*) thd->alloc(db_len + tbl_len + 2); if (!db.str) { @@ -1404,6 +1405,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, status_var_increment(thd->status_var.com_other); thd->enable_slow_log= opt_log_slow_admin_statements; + thd->query_plan_flags|= QPLAN_ADMIN; if (check_global_access(thd, REPL_SLAVE_ACL)) break; @@ -1638,6 +1640,19 @@ void log_slow_statement(THD *thd) if (unlikely(thd->in_sub_stmt)) DBUG_VOID_RETURN; // Don't set time for sub stmt + /* Follow the slow log filter configuration. */ + DBUG_ASSERT(thd->variables.log_slow_filter != 0); + if (!(thd->variables.log_slow_filter & thd->query_plan_flags)) + DBUG_VOID_RETURN; + + /* + If rate limiting of slow log writes is enabled, decide whether to log + this query to the log or not. + */ + if (thd->variables.log_slow_rate_limit > 1 && + (global_query_id % thd->variables.log_slow_rate_limit) != 0) + DBUG_VOID_RETURN; + /* Do not log administrative statements unless the appropriate option is set; do not log into slow log if reading from backup. @@ -2353,6 +2368,7 @@ mysql_execute_command(THD *thd) check_global_access(thd, FILE_ACL)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; + thd->query_plan_flags|= QPLAN_ADMIN; res = mysql_backup_table(thd, first_table); select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -2365,6 +2381,7 @@ mysql_execute_command(THD *thd) check_global_access(thd, FILE_ACL)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; + thd->query_plan_flags|= QPLAN_ADMIN; res = mysql_restore_table(thd, first_table); select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -2750,6 +2767,7 @@ end_with_restore_list: ALTER TABLE. */ thd->enable_slow_log= opt_log_slow_admin_statements; + thd->query_plan_flags|= QPLAN_ADMIN; bzero((char*) &create_info, sizeof(create_info)); create_info.db_type= 0; @@ -2869,6 +2887,7 @@ end_with_restore_list: } thd->enable_slow_log= opt_log_slow_admin_statements; + thd->query_plan_flags|= QPLAN_ADMIN; res= mysql_alter_table(thd, select_lex->db, lex->name.str, &create_info, first_table, @@ -2956,6 +2975,7 @@ end_with_restore_list: UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; + thd->query_plan_flags|= QPLAN_ADMIN; res= mysql_repair_table(thd, first_table, &lex->check_opt); /* ! we write after unlocking the table */ if (!res && !lex->no_write_to_binlog) @@ -2976,6 +2996,7 @@ end_with_restore_list: UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; + thd->query_plan_flags|= QPLAN_ADMIN; res = mysql_check_table(thd, first_table, &lex->check_opt); select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -2988,6 +3009,7 @@ end_with_restore_list: UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; + thd->query_plan_flags|= QPLAN_ADMIN; res= mysql_analyze_table(thd, first_table, &lex->check_opt); /* ! we write after unlocking the table */ if (!res && !lex->no_write_to_binlog) @@ -3009,6 +3031,7 @@ end_with_restore_list: UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; + thd->query_plan_flags|= QPLAN_ADMIN; res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ? mysql_recreate_table(thd, first_table) : mysql_optimize_table(thd, first_table, &lex->check_opt); @@ -5658,6 +5681,8 @@ void mysql_reset_thd_for_next_command(THD *thd) thd->total_warn_count=0; // Warnings for this query thd->rand_used= 0; thd->sent_row_count= thd->examined_row_count= 0; + thd->query_plan_flags= QPLAN_INIT; + thd->query_plan_fsort_passes= 0; /* Because we come here only for start of top-statements, binlog format is diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ce7507b2806..68899d40a6a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6547,7 +6547,10 @@ make_join_readinfo(JOIN *join, ulonglong options) { join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED; if (statistics) + { status_var_increment(join->thd->status_var.select_scan_count); + join->thd->query_plan_flags|= QPLAN_FULL_SCAN; + } } } else @@ -6561,7 +6564,10 @@ make_join_readinfo(JOIN *join, ulonglong options) { join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED; if (statistics) + { status_var_increment(join->thd->status_var.select_full_join_count); + join->thd->query_plan_flags|= QPLAN_FULL_JOIN; + } } } if (!table->no_keyread) @@ -9724,6 +9730,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, (ulong) rows_limit,test(group))); status_var_increment(thd->status_var.created_tmp_tables); + thd->query_plan_flags|= QPLAN_TMP_TABLE; if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES)) temp_pool_slot = bitmap_lock_set_next(&temp_pool); @@ -10610,6 +10617,7 @@ static bool create_internal_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, goto err; } status_var_increment(table->in_use->status_var.created_tmp_disk_tables); + table->in_use->query_plan_flags|= QPLAN_TMP_DISK; share->db_record_offset= 1; DBUG_RETURN(0); err: diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3687dc0751d..8f1e173b5e9 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4567,8 +4567,7 @@ static bool store_trigger(THD *thd, TABLE *table, LEX_STRING *db_name, table->field[14]->store(STRING_WITH_LEN("OLD"), cs); table->field[15]->store(STRING_WITH_LEN("NEW"), cs); - sys_var_thd_sql_mode::symbolic_mode_representation(thd, sql_mode, - &sql_mode_rep); + sys_var::make_set(thd, sql_mode, &sql_mode_typelib, &sql_mode_rep); table->field[17]->store(sql_mode_rep.str, sql_mode_rep.length, cs); table->field[18]->store(definer_buffer->str, definer_buffer->length, cs); table->field[19]->store(client_cs_name->str, client_cs_name->length, cs); @@ -5161,8 +5160,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) /* SQL_MODE */ { LEX_STRING sql_mode; - sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode, - &sql_mode); + sys_var::make_set(thd, et.sql_mode, &sql_mode_typelib, &sql_mode); sch_table->field[ISE_SQL_MODE]-> store(sql_mode.str, sql_mode.length, scs); } @@ -6867,9 +6865,7 @@ static bool show_create_trigger_impl(THD *thd, &trg_connection_cl_name, &trg_db_cl_name); - sys_var_thd_sql_mode::symbolic_mode_representation(thd, - trg_sql_mode, - &trg_sql_mode_str); + sys_var::make_set(thd, trg_sql_mode, &sql_mode_typelib, &trg_sql_mode_str); /* Resolve trigger client character set. */ diff --git a/sql/strfunc.cc b/sql/strfunc.cc index 5ff2efe2020..0153381f85b 100644 --- a/sql/strfunc.cc +++ b/sql/strfunc.cc @@ -45,6 +45,7 @@ ulonglong find_set(TYPELIB *lib, const char *str, uint length, CHARSET_INFO *strip= cs ? cs : &my_charset_latin1; const char *end= str + strip->cset->lengthsp(strip, str, length); ulonglong found= 0; + *err_pos= 0; // No error yet if (str != end) { @@ -74,9 +75,13 @@ ulonglong find_set(TYPELIB *lib, const char *str, uint length, find_type(lib, start, var_len, (bool) 0); if (!find) { - *err_pos= (char*) start; - *err_len= var_len; - *set_warning= 1; + /* Report first error */ + if (!*err_pos) + { + *err_pos= (char*) start; + *err_len= var_len; + *set_warning= 1; + } } else found|= ((longlong) 1 << (find - 1)); @@ -148,8 +153,10 @@ static uint parse_name(TYPELIB *lib, const char **strpos, const char *end, } } else - for (; pos != end && *pos != '=' && *pos !=',' ; pos++); - + { + for (; pos != end && *pos != '=' && *pos !=',' ; pos++) + ; + } uint var_len= (uint) (pos - start); /* Determine which flag it is */ uint find= cs ? find_type2(lib, start, var_len, cs) : diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c index d798ef50d7e..239fdb3fbc4 100644 --- a/storage/myisam/mi_extra.c +++ b/storage/myisam/mi_extra.c @@ -260,9 +260,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) case HA_EXTRA_PREPARE_FOR_DROP: pthread_mutex_lock(&THR_LOCK_myisam); share->last_version= 0L; /* Impossible version */ -#ifdef __WIN__REMOVE_OBSOLETE_WORKAROUND - /* Close the isam and data files as Win32 can't drop an open table */ pthread_mutex_lock(&share->intern_lock); + /* Flush pages that we don't need anymore */ if (flush_key_blocks(share->key_cache, share->kfile, (function == HA_EXTRA_PREPARE_FOR_DROP ? FLUSH_IGNORE_CHANGED : FLUSH_RELEASE))) @@ -272,6 +271,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) mi_print_error(info->s, HA_ERR_CRASHED); mi_mark_crashed(info); /* Fatal error found */ } +#ifdef __WIN__REMOVE_OBSOLETE_WORKAROUND + /* Close the isam and data files as Win32 can't drop an open table */ if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) { info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); @@ -304,8 +305,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) } } share->kfile= -1; /* Files aren't open anymore */ - pthread_mutex_unlock(&share->intern_lock); #endif + pthread_mutex_unlock(&share->intern_lock); pthread_mutex_unlock(&THR_LOCK_myisam); break; case HA_EXTRA_FLUSH: diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index f3d9934ed8c..ebee8826c3b 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -582,7 +582,7 @@ int _mi_decrement_open_count(MI_INFO *info) { uint old_lock=info->lock_type; share->global_changed=0; - lock_error=mi_lock_database(info,F_WRLCK); + lock_error= my_disable_locking ? 0 : mi_lock_database(info,F_WRLCK); /* Its not fatal even if we couldn't get the lock ! */ if (share->state.open_count > 0) { @@ -592,7 +592,7 @@ int _mi_decrement_open_count(MI_INFO *info) sizeof(share->state.header), MYF(MY_NABP)); } - if (!lock_error) + if (!lock_error && !my_disable_locking) lock_error=mi_lock_database(info,old_lock); } return test(lock_error || write_error); -- cgit v1.2.1