summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--KNOWN_BUGS.txt89
-rw-r--r--README41
-rw-r--r--mysql-test/r/log_slow.result60
-rw-r--r--mysql-test/r/variables.result2
-rw-r--r--mysql-test/t/log_slow.test42
-rw-r--r--sql/Makefile.am2
-rw-r--r--sql/event_data_objects.cc3
-rw-r--r--sql/events.cc3
-rw-r--r--sql/filesort.cc3
-rw-r--r--sql/log.cc41
-rw-r--r--sql/log_slow.h107
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/mysqld.cc58
-rw-r--r--sql/set_var.cc164
-rw-r--r--sql/set_var.h36
-rw-r--r--sql/slave.cc1
-rw-r--r--sql/sp_head.cc12
-rw-r--r--sql/sql_cache.cc5
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_class.h7
-rw-r--r--sql/sql_parse.cc25
-rw-r--r--sql/sql_select.cc8
-rw-r--r--sql/sql_show.cc10
-rw-r--r--sql/strfunc.cc17
-rw-r--r--storage/myisam/mi_extra.c7
-rw-r--r--storage/myisam/mi_locking.c4
26 files changed, 546 insertions, 204 deletions
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= &not_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 <m_ctype.h>
#include <my_dir.h>
@@ -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) ||
@@ -3700,6 +3775,24 @@ int set_var_password::update(THD *thd)
}
/****************************************************************************
+ 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<Item> *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<Item> *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<Item> *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<Item> &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);