From: Bjorn Munch Date: September 2 2010 8:17am Subject: bzr push into mysql-5.5-mtr branch (bjorn.munch:3084 to 3086) List-Archive: http://lists.mysql.com/commits/117402 Message-Id: <201009020818.o828I66g004463@khepri15.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1787014902==" --===============1787014902== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline 3086 Bjorn Munch 2010-09-01 [merge] upmerge 56383 modified: mysql-test/mysql-test-run.pl 3085 Bjorn Munch 2010-09-01 [merge] merge from 5.5 added: include/mysql/service_thd_wait.h include/mysql/service_thread_scheduler.h libservices/my_thread_scheduler_service.c libservices/thd_wait_service.c sql/sql_callback.h modified: client/mysqltest.cc include/Makefile.am include/mysql/plugin.h include/mysql/plugin_audit.h.pp include/mysql/plugin_ftparser.h.pp include/mysql/services.h include/service_versions.h include/thr_lock.h include/violite.h libservices/CMakeLists.txt libservices/Makefile.am mysql-test/r/delete.result mysql-test/r/func_group.result mysql-test/r/mysqld--help-notwin.result mysql-test/r/mysqld--help-win.result mysql-test/r/range.result mysql-test/suite/innodb/r/innodb_mysql.result mysql-test/suite/innodb/t/innodb_mysql.test mysql-test/suite/rpl/r/rpl_flush_logs.result mysql-test/suite/rpl/t/rpl_flush_logs.test mysql-test/t/delete.test mysql-test/t/func_group.test mysql-test/t/range.test mysys/my_init.c mysys/thr_lock.c sql/authors.h sql/item_sum.cc sql/item_sum.h sql/log.cc sql/mysqld.cc sql/mysqld.h sql/opt_range.cc sql/scheduler.cc sql/scheduler.h sql/sql_class.cc sql/sql_class.h sql/sql_connect.cc sql/sql_connect.h sql/sql_plugin_services.h sql/sql_select.cc sql/sql_show.cc sql/sql_yacc.yy sql/sys_vars.cc storage/innobase/buf/buf0flu.c storage/innobase/buf/buf0rea.c storage/innobase/srv/srv0srv.c vio/vio.c vio/vio_priv.h vio/viosocket.c vio/viossl.c 3084 Bjorn Munch 2010-08-30 [merge] upmerge 55178,55413 modified: .bzr-mysql/default.conf client/mysqltest.cc mysql-test/lib/mtr_cases.pm mysql-test/mysql-test-run.pl mysql-test/r/mysqltest.result mysql-test/t/mysqltest.test === modified file 'client/mysqltest.cc' --- a/client/mysqltest.cc 2010-08-30 13:19:46 +0000 +++ b/client/mysqltest.cc 2010-09-01 13:49:43 +0000 @@ -5255,10 +5255,8 @@ void do_connect(struct st_command *comma } #endif -#ifndef EMBEDDED_LIBRARY if (opt_protocol) mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol); -#endif #ifdef HAVE_SMEM if (con_shm) @@ -7992,10 +7990,8 @@ int main(int argc, char **argv) mysql_options(&con->mysql, MYSQL_SET_CHARSET_DIR, opt_charsets_dir); -#ifndef EMBEDDED_LIBRARY if (opt_protocol) mysql_options(&con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); -#endif #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) === modified file 'include/Makefile.am' --- a/include/Makefile.am 2010-07-23 20:14:35 +0000 +++ b/include/Makefile.am 2010-08-16 12:50:27 +0000 @@ -26,6 +26,8 @@ HEADERS_ABI = mysql.h mysql_com.h mysql pkginclude_HEADERS = $(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \ my_xml.h mysql_embed.h mysql/services.h \ mysql/service_my_snprintf.h mysql/service_thd_alloc.h \ + mysql/service_thread_scheduler.h \ + mysql/service_thd_wait.h \ my_pthread.h my_no_pthread.h \ decimal.h errmsg.h my_global.h my_net.h \ my_getopt.h sslopt-longopts.h my_dir.h \ === modified file 'include/mysql/plugin.h' --- a/include/mysql/plugin.h 2010-08-18 07:48:38 +0000 +++ b/include/mysql/plugin.h 2010-08-30 14:07:40 +0000 @@ -71,7 +71,7 @@ typedef struct st_mysql_xid MYSQL_XID; Plugin API. Common for all plugin types. */ -#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101 +#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0102 /* The allowable types of plugins === modified file 'include/mysql/plugin_audit.h.pp' --- a/include/mysql/plugin_audit.h.pp 2010-08-27 06:45:35 +0000 +++ b/include/mysql/plugin_audit.h.pp 2010-08-30 14:07:40 +0000 @@ -31,6 +31,27 @@ void *thd_memdup(void* thd, const void* MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str, const char *str, unsigned int size, int allocate_lex_string); +#include +typedef enum _thd_wait_type_e { + THD_WAIT_MUTEX= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_TABLE_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(void*, thd_wait_type); + void (*thd_wait_end_func)(void*); +} *thd_wait_service; +void thd_wait_begin(void* thd, thd_wait_type wait_type); +void thd_wait_end(void* thd); +#include +struct scheduler_functions; +extern struct my_thread_scheduler_service { + int (*set)(struct scheduler_functions *scheduler); + int (*reset)(); +} *my_thread_scheduler_service; +int my_thread_scheduler_set(struct scheduler_functions *scheduler); +int my_thread_scheduler_reset(); struct st_mysql_xid { long formatID; long gtrid_length; === modified file 'include/mysql/plugin_ftparser.h.pp' --- a/include/mysql/plugin_ftparser.h.pp 2010-08-27 06:45:35 +0000 +++ b/include/mysql/plugin_ftparser.h.pp 2010-08-30 14:07:40 +0000 @@ -31,6 +31,27 @@ void *thd_memdup(void* thd, const void* MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str, const char *str, unsigned int size, int allocate_lex_string); +#include +typedef enum _thd_wait_type_e { + THD_WAIT_MUTEX= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_TABLE_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4 +} thd_wait_type; +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(void*, thd_wait_type); + void (*thd_wait_end_func)(void*); +} *thd_wait_service; +void thd_wait_begin(void* thd, thd_wait_type wait_type); +void thd_wait_end(void* thd); +#include +struct scheduler_functions; +extern struct my_thread_scheduler_service { + int (*set)(struct scheduler_functions *scheduler); + int (*reset)(); +} *my_thread_scheduler_service; +int my_thread_scheduler_set(struct scheduler_functions *scheduler); +int my_thread_scheduler_reset(); struct st_mysql_xid { long formatID; long gtrid_length; === added file 'include/mysql/service_thd_wait.h' --- a/include/mysql/service_thd_wait.h 1970-01-01 00:00:00 +0000 +++ b/include/mysql/service_thd_wait.h 2010-06-07 14:01:39 +0000 @@ -0,0 +1,83 @@ +/* Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + + 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 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 */ + +#ifndef MYSQL_SERVICE_THD_WAIT_INCLUDED +#define MYSQL_SERVICE_THD_WAIT_INCLUDED + +/** + @file include/mysql/service_thd_wait.h + This service provides functions for plugins and storage engines to report + when they are going to sleep/stall. + + SYNOPSIS + thd_wait_begin() - call just before a wait begins + thd Thread object + Use NULL if the thd is NOT known. + wait_type Type of wait + 1 -- short wait (e.g. for mutex) + 2 -- medium wait (e.g. for disk io) + 3 -- large wait (e.g. for locked row/table) + NOTES + This is used by the threadpool to have better knowledge of which + threads that currently are actively running on CPUs. When a thread + reports that it's going to sleep/stall, the threadpool scheduler is + free to start another thread in the pool most likely. The expected wait + time is simply an indication of how long the wait is expected to + become, the real wait time could be very different. + + thd_wait_end() called immediately after the wait is complete + + thd_wait_end() MUST be called if thd_wait_begin() was called. + + Using thd_wait_...() service is optional but recommended. Using it will + improve performance as the thread pool will be more active at managing the + thread workload. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum _thd_wait_type_e { + THD_WAIT_MUTEX= 1, + THD_WAIT_DISKIO= 2, + THD_WAIT_ROW_TABLE_LOCK= 3, + THD_WAIT_GLOBAL_LOCK= 4 +} thd_wait_type; + +extern struct thd_wait_service_st { + void (*thd_wait_begin_func)(MYSQL_THD, thd_wait_type); + void (*thd_wait_end_func)(MYSQL_THD); +} *thd_wait_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define thd_wait_begin(_THD, _WAIT_TYPE) \ + thd_wait_service->thd_wait_begin_func(_THD, _WAIT_TYPE) +#define thd_wait_end(_THD) thd_wait_service->thd_wait_end_func(_THD) + +#else + +void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type); +void thd_wait_end(MYSQL_THD thd); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + === added file 'include/mysql/service_thread_scheduler.h' --- a/include/mysql/service_thread_scheduler.h 1970-01-01 00:00:00 +0000 +++ b/include/mysql/service_thread_scheduler.h 2010-06-07 14:01:39 +0000 @@ -0,0 +1,65 @@ +/* + Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + + 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 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 +*/ + +#ifndef SERVICE_THREAD_SCHEDULER_INCLUDED +#define SERVICE_THREAD_SCHEDULER_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +struct scheduler_functions; + +extern struct my_thread_scheduler_service { + int (*set)(struct scheduler_functions *scheduler); + int (*reset)(); +} *my_thread_scheduler_service; + +#ifdef MYSQL_DYNAMIC_PLUGIN + +#define my_thread_scheduler_set(F) my_thread_scheduler_service->set((F)) +#define my_thread_scheduler_reset() my_thread_scheduler_service->reset() + +#else + +/** + Set the thread scheduler to use for the server. + + @param scheduler Pointer to scheduler callbacks to use. + @retval 0 Scheduler installed correctly. + @retval 1 Invalid value (NULL) used for scheduler. +*/ +int my_thread_scheduler_set(struct scheduler_functions *scheduler); + +/** + Restore the previous thread scheduler. + + @note If no thread scheduler was installed previously with + thd_set_thread_scheduler, this function will report an error. + + @retval 0 Scheduler installed correctly. + @retval 1 No scheduler installed. +*/ +int my_thread_scheduler_reset(); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SERVICE_THREAD_SCHEDULER_INCLUDED */ === modified file 'include/mysql/services.h' --- a/include/mysql/services.h 2009-11-02 20:05:42 +0000 +++ b/include/mysql/services.h 2010-06-07 14:01:39 +0000 @@ -20,6 +20,8 @@ extern "C" { #include #include +#include +#include #ifdef __cplusplus } === modified file 'include/service_versions.h' --- a/include/service_versions.h 2009-11-02 20:05:42 +0000 +++ b/include/service_versions.h 2010-06-07 14:01:39 +0000 @@ -21,4 +21,5 @@ #define VERSION_my_snprintf 0x0100 #define VERSION_thd_alloc 0x0100 - +#define VERSION_thd_wait 0x0100 +#define VERSION_my_thread_scheduler 0x0100 === modified file 'include/thr_lock.h' --- a/include/thr_lock.h 2010-07-27 12:42:36 +0000 +++ b/include/thr_lock.h 2010-08-16 12:50:27 +0000 @@ -155,6 +155,8 @@ void thr_downgrade_write_lock(THR_LOC enum thr_lock_type new_lock_type); my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data, ulong lock_wait_timeout); +void thr_set_lock_wait_callback(void (*before_wait)(void), + void (*after_wait)(void)); #ifdef __cplusplus } #endif === modified file 'include/violite.h' --- a/include/violite.h 2010-04-13 15:04:45 +0000 +++ b/include/violite.h 2010-06-07 14:01:39 +0000 @@ -217,6 +217,7 @@ struct st_vio void (*timeout)(Vio*, unsigned int which, unsigned int timeout); my_bool (*poll_read)(Vio *vio, uint timeout); my_bool (*is_connected)(Vio*); + my_bool (*has_data) (Vio*); #ifdef HAVE_OPENSSL void *ssl_arg; #endif === modified file 'libservices/CMakeLists.txt' --- a/libservices/CMakeLists.txt 2010-08-12 15:19:57 +0000 +++ b/libservices/CMakeLists.txt 2010-08-16 12:50:27 +0000 @@ -15,7 +15,11 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) -SET(MYSQLSERVICES_SOURCES my_snprintf_service.c thd_alloc_service.c) +SET(MYSQLSERVICES_SOURCES + my_snprintf_service.c + thd_alloc_service.c + thd_wait_service.c + my_thread_scheduler_service.c) ADD_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES}) INSTALL(TARGETS mysqlservices DESTINATION ${INSTALL_LIBDIR}) === modified file 'libservices/Makefile.am' --- a/libservices/Makefile.am 2009-11-02 20:05:42 +0000 +++ b/libservices/Makefile.am 2010-06-07 14:01:39 +0000 @@ -15,5 +15,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include pkglib_LIBRARIES = libmysqlservices.a -libmysqlservices_a_SOURCES = my_snprintf_service.c thd_alloc_service.c +libmysqlservices_a_SOURCES = my_snprintf_service.c thd_alloc_service.c \ + thd_wait_service.c \ + my_thread_scheduler_service.c EXTRA_DIST = CMakeLists.txt === added file 'libservices/my_thread_scheduler_service.c' --- a/libservices/my_thread_scheduler_service.c 1970-01-01 00:00:00 +0000 +++ b/libservices/my_thread_scheduler_service.c 2010-06-07 14:01:39 +0000 @@ -0,0 +1,21 @@ +/* + Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + + 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 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 +*/ + +#include +SERVICE_VERSION my_thread_scheduler_service= + (void*)VERSION_my_thread_scheduler; === added file 'libservices/thd_wait_service.c' --- a/libservices/thd_wait_service.c 1970-01-01 00:00:00 +0000 +++ b/libservices/thd_wait_service.c 2010-06-07 14:01:39 +0000 @@ -0,0 +1,19 @@ +/* + Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + + 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 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 +*/ + +#include +SERVICE_VERSION *thd_wait_service= (void*)VERSION_thd_wait; === modified file 'mysql-test/mysql-test-run.pl' --- a/mysql-test/mysql-test-run.pl 2010-08-30 13:19:46 +0000 +++ b/mysql-test/mysql-test-run.pl 2010-09-01 13:52:31 +0000 @@ -244,6 +244,7 @@ my $opt_repeat= 1; my $opt_retry= 3; my $opt_retry_failure= env_or_val(MTR_RETRY_FAILURE => 2); my $opt_reorder= 1; +my $opt_force_restart= 0; my $opt_strace_client; @@ -944,6 +945,7 @@ sub command_line_setup { 'report-features' => \$opt_report_features, 'comment=s' => \$opt_comment, 'fast' => \$opt_fast, + 'force-restart' => \$opt_force_restart, 'reorder!' => \$opt_reorder, 'enable-disabled' => \&collect_option, 'verbose+' => \$opt_verbose, @@ -4577,6 +4579,11 @@ sub server_need_restart { return 1; } + if ( $opt_force_restart ) { + mtr_verbose_restart($server, "forced restart turned on"); + return 1; + } + if ( $tinfo->{template_path} ne $current_config_name) { mtr_verbose_restart($server, "using different config file"); @@ -5605,6 +5612,7 @@ Misc options servers to exit before finishing the process fast Run as fast as possible, dont't wait for servers to shutdown etc. + force-restart Always restart servers between tests parallel=N Run tests in N parallel threads (default=1) Use parallel=auto for auto-setting of N repeat=N Run each test N number of times === modified file 'mysql-test/r/delete.result' --- a/mysql-test/r/delete.result 2010-05-23 20:41:18 +0000 +++ b/mysql-test/r/delete.result 2010-08-30 22:22:01 +0000 @@ -499,4 +499,13 @@ INDEX(a), INDEX(b), INDEX(c)); INSERT INTO t1 VALUES (1,2,3), (4,5,6), (7,8,9); DELETE FROM t1 WHERE a = 10 OR b = 20 ORDER BY c LIMIT 1; DROP TABLE t1; +# +# Bug #53034: Multiple-table DELETE statements not accepting +# "Access compatibility" syntax +# +CREATE TABLE t1 (id INT); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 LIKE t1; +DELETE FROM t1.*, test.t2.*, a.* USING t1, t2, t3 AS a; +DROP TABLE t1, t2, t3; End of 5.1 tests === modified file 'mysql-test/r/func_group.result' --- a/mysql-test/r/func_group.result 2010-08-25 09:21:54 +0000 +++ b/mysql-test/r/func_group.result 2010-08-30 08:36:02 +0000 @@ -1713,6 +1713,17 @@ f1 f2 f3 f4 f1 = f2 NULL NULL NULL NULL NULL drop table t1; # +# Bug #54465: assert: field_types == 0 || field_types[field_pos] == +# MYSQL_TYPE_LONGLONG +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); +SELECT MAX((SELECT 1 FROM t1 ORDER BY @var LIMIT 1)) m FROM t1 t2, t1 +ORDER BY t1.a; +m +1 +DROP TABLE t1; +# End of 5.1 tests # # Bug#55648: Server crash on MIN/MAX on maximum time value === modified file 'mysql-test/r/mysqld--help-notwin.result' --- a/mysql-test/r/mysqld--help-notwin.result 2010-08-28 16:36:17 +0000 +++ b/mysql-test/r/mysqld--help-notwin.result 2010-08-30 14:07:40 +0000 @@ -688,7 +688,7 @@ The following options may be given as th How many threads we should keep in a cache for reuse --thread-handling=name Define threads usage for handling queries, one of - one-thread-per-connection, no-threads + one-thread-per-connection, no-threads, loaded-dynamically --thread-stack=# The stack size for each thread --time-format=name The TIME format (ignored) --timed-mutexes Specify whether to time mutexes (only InnoDB mutexes are === modified file 'mysql-test/r/mysqld--help-win.result' --- a/mysql-test/r/mysqld--help-win.result 2010-08-28 16:36:17 +0000 +++ b/mysql-test/r/mysqld--help-win.result 2010-08-30 14:07:40 +0000 @@ -692,7 +692,7 @@ The following options may be given as th How many threads we should keep in a cache for reuse --thread-handling=name Define threads usage for handling queries, one of - one-thread-per-connection, no-threads + one-thread-per-connection, no-threads, loaded-dynamically --thread-stack=# The stack size for each thread --time-format=name The TIME format (ignored) --timed-mutexes Specify whether to time mutexes (only InnoDB mutexes are === modified file 'mysql-test/r/range.result' --- a/mysql-test/r/range.result 2010-08-11 15:55:07 +0000 +++ b/mysql-test/r/range.result 2010-08-26 12:35:38 +0000 @@ -1653,4 +1653,17 @@ a b 0 0 1 1 DROP TABLE t1; +# +# Bug #54802: 'NOT BETWEEN' evaluation is incorrect +# +CREATE TABLE t1 (c_key INT, c_notkey INT, KEY(c_key)); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); +EXPLAIN SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL c_key NULL NULL NULL 3 Using where +SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key; +c_key c_notkey +1 1 +3 3 +DROP TABLE t1; End of 5.1 tests === modified file 'mysql-test/suite/innodb/r/innodb_mysql.result' --- a/mysql-test/suite/innodb/r/innodb_mysql.result 2010-08-25 10:22:34 +0000 +++ b/mysql-test/suite/innodb/r/innodb_mysql.result 2010-08-30 08:36:02 +0000 @@ -2549,6 +2549,64 @@ LOCK TABLES t1 READ; ALTER TABLE t1 COMMENT 'test'; UNLOCK TABLES; DROP TABLE t1; +# +# Bug#55656: mysqldump can be slower after bug #39653 fix +# +CREATE TABLE t1 (a INT , b INT, c INT, d INT, +KEY (b), PRIMARY KEY (a,b)) ENGINE=INNODB; +INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 4 +ref NULL +rows 3 +Extra Using index +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 8 +ref NULL +rows 3 +Extra Using index +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 13 +ref NULL +rows 3 +Extra Using index +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c,d); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key PRIMARY +key_len 8 +ref NULL +rows 3 +Extra Using index +DROP TABLE t1; +# End of 5.1 tests # # Test for bug #39932 "create table fails if column for FK is in different === modified file 'mysql-test/suite/innodb/t/innodb_mysql.test' --- a/mysql-test/suite/innodb/t/innodb_mysql.test 2010-08-20 11:22:46 +0000 +++ b/mysql-test/suite/innodb/t/innodb_mysql.test 2010-08-27 11:33:32 +0000 @@ -746,6 +746,30 @@ UNLOCK TABLES; DROP TABLE t1; +--echo # +--echo # Bug#55656: mysqldump can be slower after bug #39653 fix +--echo # + +CREATE TABLE t1 (a INT , b INT, c INT, d INT, + KEY (b), PRIMARY KEY (a,b)) ENGINE=INNODB; +INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c,d); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP TABLE t1; + +--echo # --echo End of 5.1 tests === modified file 'mysql-test/suite/rpl/r/rpl_flush_logs.result' --- a/mysql-test/suite/rpl/r/rpl_flush_logs.result 2009-12-03 08:59:58 +0000 +++ b/mysql-test/suite/rpl/r/rpl_flush_logs.result 2010-08-30 09:09:28 +0000 @@ -4,12 +4,8 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -# Make sure the 'master_log.err-old' file does not -# exist before execute 'flush error logs' statement. # Test if support 'flush error logs' statement. flush error logs; -# Check the 'master_log.err-old' file is created -# after executed 'flush error logs' statement. # Make sure binary logs was not be flushed # after execute 'flush error logs' statement. # Make sure relay logs was not be flushed @@ -42,12 +38,8 @@ flush binary logs; # after executed 'flush binary logs' statement. # Make sure the 'slave-relay-bin.000007' file does not exist # exist before execute 'flush error logs, relay logs' statement. -# Make sure the 'master_log.err-old' file does not exist -# before execute 'flush error logs, relay logs' statement. # Test if support to combine all kinds of logs into one statement. flush error logs, relay logs; -# Check the 'master_log.err-old' file is created -# after executed 'flush error logs, relay logs' statement. # Make sure binary logs was not be flushed # after execute 'flush error logs, relay logs' statement. # Check the 'slave-relay-bin.000007' file is created after @@ -55,12 +47,8 @@ flush error logs, relay logs; # Make sure the 'slave-relay-bin.000008' and 'slave-relay-bin.000009' # files do not exist before execute 'flush error logs, relay logs' # statement. -# Make sure the 'master_log.err-old' file does not exist -# before execute 'flush logs' statement. # Test if 'flush logs' statement works fine and flush all the logs. flush logs; -# Check the 'master_log.err-old' file is created -# after executed 'flush logs' statement. # Check 'master-bin.000003' is created # after execute 'flush logs' statement. # Check the 'slave-relay-bin.000008' and 'slave-relay-bin.000009' === modified file 'mysql-test/suite/rpl/t/rpl_flush_logs.test' --- a/mysql-test/suite/rpl/t/rpl_flush_logs.test 2009-12-03 08:59:58 +0000 +++ b/mysql-test/suite/rpl/t/rpl_flush_logs.test 2010-08-30 09:09:28 +0000 @@ -9,17 +9,10 @@ connection master; # Test 'flush error logs' statement. ---echo # Make sure the 'master_log.err-old' file does not ---echo # exist before execute 'flush error logs' statement. ---error 1 -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; --echo # Test if support 'flush error logs' statement. flush error logs; ---echo # Check the 'master_log.err-old' file is created ---echo # after executed 'flush error logs' statement. -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; file_exists $MYSQLTEST_VARDIR/tmp/master_log.err; --echo # Make sure binary logs was not be flushed @@ -109,19 +102,10 @@ sync_slave_with_master; file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000007; connection master; -remove_file $MYSQLTEST_VARDIR/tmp/master_log.err-old; - ---echo # Make sure the 'master_log.err-old' file does not exist ---echo # before execute 'flush error logs, relay logs' statement. ---error 1 -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; --echo # Test if support to combine all kinds of logs into one statement. flush error logs, relay logs; ---echo # Check the 'master_log.err-old' file is created ---echo # after executed 'flush error logs, relay logs' statement. -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; file_exists $MYSQLTEST_VARDIR/tmp/master_log.err; --echo # Make sure binary logs was not be flushed @@ -145,19 +129,10 @@ file_exists $MYSQLTEST_VARDIR/mysqld.2/d file_exists $MYSQLTEST_VARDIR/mysqld.2/data/slave-relay-bin.000009; connection master; -remove_file $MYSQLTEST_VARDIR/tmp/master_log.err-old; - ---echo # Make sure the 'master_log.err-old' file does not exist ---echo # before execute 'flush logs' statement. ---error 1 -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; --echo # Test if 'flush logs' statement works fine and flush all the logs. flush logs; ---echo # Check the 'master_log.err-old' file is created ---echo # after executed 'flush logs' statement. -file_exists $MYSQLTEST_VARDIR/tmp/master_log.err-old; file_exists $MYSQLTEST_VARDIR/tmp/master_log.err; --echo # Check 'master-bin.000003' is created === modified file 'mysql-test/t/delete.test' --- a/mysql-test/t/delete.test 2010-05-23 20:41:18 +0000 +++ b/mysql-test/t/delete.test 2010-08-30 22:22:01 +0000 @@ -540,4 +540,17 @@ DELETE FROM t1 WHERE a = 10 OR b = 20 OR DROP TABLE t1; +--echo # +--echo # Bug #53034: Multiple-table DELETE statements not accepting +--echo # "Access compatibility" syntax +--echo # + +CREATE TABLE t1 (id INT); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 LIKE t1; + +DELETE FROM t1.*, test.t2.*, a.* USING t1, t2, t3 AS a; + +DROP TABLE t1, t2, t3; + --echo End of 5.1 tests === modified file 'mysql-test/t/func_group.test' --- a/mysql-test/t/func_group.test 2010-08-25 09:21:54 +0000 +++ b/mysql-test/t/func_group.test 2010-08-30 08:36:02 +0000 @@ -1082,6 +1082,20 @@ select a.f1 as a, b.f4 as b, a.f1 > b.f4 from t1 a, t1 b; select *, f1 = f2 from t1; drop table t1; + +--echo # +--echo # Bug #54465: assert: field_types == 0 || field_types[field_pos] == +--echo # MYSQL_TYPE_LONGLONG +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); + +SELECT MAX((SELECT 1 FROM t1 ORDER BY @var LIMIT 1)) m FROM t1 t2, t1 + ORDER BY t1.a; + +DROP TABLE t1; + --echo # --echo End of 5.1 tests === modified file 'mysql-test/t/range.test' --- a/mysql-test/t/range.test 2010-08-11 12:13:59 +0000 +++ b/mysql-test/t/range.test 2010-08-24 15:51:32 +0000 @@ -1313,4 +1313,16 @@ SELECT * FROM t1 FORCE INDEX (PRIMARY) DROP TABLE t1; +--echo # +--echo # Bug #54802: 'NOT BETWEEN' evaluation is incorrect +--echo # + +CREATE TABLE t1 (c_key INT, c_notkey INT, KEY(c_key)); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); + +EXPLAIN SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key; +SELECT * FROM t1 WHERE 2 NOT BETWEEN c_notkey AND c_key; + +DROP TABLE t1; + --echo End of 5.1 tests === modified file 'mysys/my_init.c' --- a/mysys/my_init.c 2010-07-23 20:16:29 +0000 +++ b/mysys/my_init.c 2010-08-16 12:50:27 +0000 @@ -477,7 +477,7 @@ static my_bool win32_init_tcp_ip() { if (win32_have_tcpip()) { - WORD wVersionRequested = MAKEWORD( 2, 0 ); + WORD wVersionRequested = MAKEWORD( 2, 2 ); WSADATA wsaData; /* Be a good citizen: maybe another lib has already initialised sockets, so dont clobber them unless necessary */ === modified file 'mysys/thr_lock.c' --- a/mysys/thr_lock.c 2010-08-06 11:29:37 +0000 +++ b/mysys/thr_lock.c 2010-08-30 14:07:40 +0000 @@ -91,6 +91,16 @@ enum thr_lock_type thr_upgraded_concurre LIST *thr_lock_thread_list; /* List of threads in use */ ulong max_write_lock_count= ~(ulong) 0L; +static void (*before_lock_wait)(void)= 0; +static void (*after_lock_wait)(void)= 0; + +void thr_set_lock_wait_callback(void (*before_wait)(void), + void (*after_wait)(void)) +{ + before_lock_wait= before_wait; + after_lock_wait= after_wait; +} + static inline mysql_cond_t *get_cond(void) { return &my_thread_var->suspend; @@ -431,6 +441,19 @@ wait_for_lock(struct st_lock_list *wait, old_proc_info= proc_info_hook(NULL, "Waiting for table level lock", __func__, __FILE__, __LINE__); + /* + Since before_lock_wait potentially can create more threads to + scheduler work for, we don't want to call the before_lock_wait + callback unless it will really start to wait. + + For similar reasons, we do not want to call before_lock_wait and + after_lock_wait for each lap around the loop, so we restrict + ourselves to call it before_lock_wait once before starting to wait + and once after the thread has exited the wait loop. + */ + if ((!thread_var->abort || in_wait_list) && before_lock_wait) + (*before_lock_wait)(); + set_timespec(wait_timeout, lock_wait_timeout); while (!thread_var->abort || in_wait_list) { @@ -462,6 +485,14 @@ wait_for_lock(struct st_lock_list *wait, /* purecov: end */ } } + + /* + We call the after_lock_wait callback once the wait loop has + finished. + */ + if (after_lock_wait) + (*after_lock_wait)(); + DBUG_PRINT("thr_lock", ("aborted: %d in_wait_list: %d", thread_var->abort, in_wait_list)); === modified file 'sql/authors.h' --- a/sql/authors.h 2010-05-11 16:02:50 +0000 +++ b/sql/authors.h 2010-08-16 12:50:27 +0000 @@ -93,6 +93,7 @@ struct show_table_authors_st show_table_ { "Arjen Lentz", "Brisbane, Australia", "Documentation (2001-2004), Dutch error messages, LOG2()" }, { "Marc Liyanage", "", "Created Mac OS X packages" }, + { "Kelly Long", "Denver, CO, USA", "Pool Of Threads" }, { "Zarko Mocnik", "", "Sorting for Slovenian language" }, { "Per-Erik Martin", "Uppsala, Sweden", "Stored Procedures (5.0)" }, { "Alexis Mikhailov", "", "User-defined functions" }, === modified file 'sql/item_sum.cc' --- a/sql/item_sum.cc 2010-08-20 11:22:46 +0000 +++ b/sql/item_sum.cc 2010-08-30 07:36:04 +0000 @@ -434,26 +434,6 @@ void Item_sum::mark_as_sum_func() } -void Item_sum::make_field(Send_field *tmp_field) -{ - if (args[0]->type() == Item::FIELD_ITEM && keep_field_type()) - { - ((Item_field*) args[0])->field->make_field(tmp_field); - /* For expressions only col_name should be non-empty string. */ - char *empty_string= (char*)""; - tmp_field->db_name= empty_string; - tmp_field->org_table_name= empty_string; - tmp_field->table_name= empty_string; - tmp_field->org_col_name= empty_string; - tmp_field->col_name= name; - if (maybe_null) - tmp_field->flags&= ~NOT_NULL_FLAG; - } - else - init_make_field(tmp_field, field_type()); -} - - void Item_sum::print(String *str, enum_query_type query_type) { /* orig_args is not filled with valid values until fix_fields() */ === modified file 'sql/item_sum.h' --- a/sql/item_sum.h 2010-07-19 17:11:47 +0000 +++ b/sql/item_sum.h 2010-08-30 07:36:04 +0000 @@ -427,7 +427,6 @@ public: forced_const= TRUE; } virtual bool const_item() const { return forced_const; } - void make_field(Send_field *field); virtual void print(String *str, enum_query_type query_type); void fix_num_length_and_dec(); === modified file 'sql/log.cc' --- a/sql/log.cc 2010-08-25 10:22:34 +0000 +++ b/sql/log.cc 2010-08-30 08:36:02 +0000 @@ -5447,70 +5447,93 @@ void sql_perror(const char *message) } +#ifdef __WIN__ +extern "C" my_bool reopen_fstreams(const char *filename, + FILE *outstream, FILE *errstream) +{ + int handle_fd; + int stream_fd; + HANDLE osfh; + + DBUG_ASSERT(filename && (outstream || errstream)); + + if ((osfh= CreateFile(filename, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | + FILE_SHARE_DELETE, NULL, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, + NULL)) == INVALID_HANDLE_VALUE) + return TRUE; + + if ((handle_fd= _open_osfhandle((intptr_t)osfh, + _O_APPEND | _O_TEXT)) == -1) + { + CloseHandle(osfh); + return TRUE; + } + + if (outstream) + { + stream_fd= _fileno(outstream); + if (_dup2(handle_fd, stream_fd) < 0) + { + CloseHandle(osfh); + return TRUE; + } + } + + if (errstream) + { + stream_fd= _fileno(errstream); + if (_dup2(handle_fd, stream_fd) < 0) + { + CloseHandle(osfh); + return TRUE; + } + } + + _close(handle_fd); + return FALSE; +} +#else +extern "C" my_bool reopen_fstreams(const char *filename, + FILE *outstream, FILE *errstream) +{ + if (outstream && !freopen(filename, "a+", outstream)) + return TRUE; + + if (errstream && !freopen(filename, "a+", errstream)) + return TRUE; + + return FALSE; +} +#endif + + /* Unfortunately, there seems to be no good way to restore the original streams upon failure. */ static bool redirect_std_streams(const char *file) { - if (freopen(file, "a+", stdout) && freopen(file, "a+", stderr)) - { - setbuf(stderr, NULL); - return FALSE; - } + if (reopen_fstreams(file, stdout, stderr)) + return TRUE; - return TRUE; + setbuf(stderr, NULL); + return FALSE; } bool flush_error_log() { - bool result=0; + bool result= 0; if (opt_error_log) { - char err_renamed[FN_REFLEN], *end; - end= strmake(err_renamed,log_error_file,FN_REFLEN-5); - strmov(end, "-old"); mysql_mutex_lock(&LOCK_error_log); -#ifdef __WIN__ - char err_temp[FN_REFLEN+5]; - /* - On Windows is necessary a temporary file for to rename - the current error file. - */ - strxmov(err_temp, err_renamed,"-tmp",NullS); - my_delete(err_temp, MYF(0)); - if (freopen(err_temp,"a+",stdout)) - { - int fd; - size_t bytes; - uchar buf[IO_SIZE]; - - freopen(err_temp,"a+",stderr); - setbuf(stderr, NULL); - my_delete(err_renamed, MYF(0)); - my_rename(log_error_file, err_renamed, MYF(0)); - redirect_std_streams(log_error_file); - - if ((fd= my_open(err_temp, O_RDONLY, MYF(0))) >= 0) - { - while ((bytes= mysql_file_read(fd, buf, IO_SIZE, MYF(0))) && - bytes != MY_FILE_ERROR) - my_fwrite(stderr, buf, bytes, MYF(0)); - mysql_file_close(fd, MYF(0)); - } - my_delete(err_temp, MYF(0)); - } - else - result= 1; -#else - my_rename(log_error_file, err_renamed, MYF(0)); - if (redirect_std_streams(log_error_file)) - result= 1; -#endif + if (redirect_std_streams(log_error_file)) + result= 1; mysql_mutex_unlock(&LOCK_error_log); } - return result; + return result; } void MYSQL_BIN_LOG::signal_update() === modified file 'sql/mysqld.cc' --- a/sql/mysqld.cc 2010-08-25 19:00:38 +0000 +++ b/sql/mysqld.cc 2010-08-30 14:07:40 +0000 @@ -64,7 +64,9 @@ #include "events.h" #include "sql_audit.h" #include "probes_mysql.h" +#include "scheduler.h" #include "debug_sync.h" +#include "sql_callback.h" #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE #include "../storage/perfschema/pfs_server.h" @@ -193,6 +195,9 @@ typedef fp_except fp_except_t; # endif #endif +extern "C" my_bool reopen_fstreams(const char *filename, + FILE *outstream, FILE *errstream); + inline void setup_fpu() { #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) @@ -456,7 +461,7 @@ ulong slave_trans_retries; uint slave_net_timeout; ulong slave_exec_mode_options; ulonglong slave_type_conversions_options; -ulong thread_cache_size=0, thread_pool_size= 0; +ulong thread_cache_size=0; ulong binlog_cache_size=0; ulonglong max_binlog_cache_size=0; ulong query_cache_size=0; @@ -898,8 +903,6 @@ my_bool opt_enable_shared_memory; HANDLE smem_event_connect_request= 0; #endif -scheduler_functions thread_scheduler; - my_bool opt_use_ssl = 0; char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL, *opt_ssl_cipher= NULL, *opt_ssl_key= NULL; @@ -1087,7 +1090,8 @@ static void close_connections(void) continue; tmp->killed= THD::KILL_CONNECTION; - thread_scheduler.post_kill_notification(tmp); + MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); + mysql_mutex_lock(&tmp->LOCK_thd_data); if (tmp->mysys_var) { tmp->mysys_var->abort=1; @@ -1100,6 +1104,7 @@ static void close_connections(void) } mysql_mutex_unlock(&tmp->mysys_var->mutex); } + mysql_mutex_unlock(&tmp->LOCK_thd_data); } mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list @@ -1479,7 +1484,7 @@ void clean_up(bool print_message) if (print_message && my_default_lc_messages && server_start_time) sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname); cleanup_errmsgs(); - thread_scheduler.end(); + MYSQL_CALLBACK(thread_scheduler, end, ()); finish_client_errs(); DBUG_PRINT("quit", ("Error messages freed")); /* Tell main we are ready */ @@ -1752,7 +1757,7 @@ static void network_init(void) DBUG_ENTER("network_init"); LINT_INIT(ret); - if (thread_scheduler.init()) + if (MYSQL_CALLBACK_ELSE(thread_scheduler, init, (), 0)) unireg_abort(1); /* purecov: inspected */ set_ports(); @@ -2000,7 +2005,7 @@ extern "C" sig_handler end_thread_signal if (thd && ! thd->bootstrap) { statistic_increment(killed_threads, &LOCK_status); - thread_scheduler.end_thread(thd,0); /* purecov: inspected */ + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd,0)); /* purecov: inspected */ } DBUG_VOID_RETURN; /* purecov: deadcode */ } @@ -2396,7 +2401,7 @@ and this may fail.\n\n"); (ulong) dflt_key_cache->key_cache_mem_size); fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size); fprintf(stderr, "max_used_connections=%lu\n", max_used_connections); - fprintf(stderr, "max_threads=%u\n", thread_scheduler.max_threads); + fprintf(stderr, "max_threads=%u\n", thread_scheduler->max_threads); fprintf(stderr, "thread_count=%u\n", thread_count); fprintf(stderr, "connection_count=%u\n", connection_count); fprintf(stderr, "It is possible that mysqld could use up to \n\ @@ -2404,7 +2409,7 @@ key_buffer_size + (read_buffer_size + so bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size + (global_system_variables.read_buff_size + global_system_variables.sortbuff_size) * - thread_scheduler.max_threads + + thread_scheduler->max_threads + max_connections * sizeof(THD)) / 1024); fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n"); @@ -2651,7 +2656,7 @@ pthread_handler_t signal_hand(void *arg This should actually be '+ max_number_of_slaves' instead of +10, but the +10 should be quite safe. */ - init_thr_alarm(thread_scheduler.max_threads + + init_thr_alarm(thread_scheduler->max_threads + global_system_variables.max_insert_delayed_threads + 10); if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT)) { @@ -3738,13 +3743,15 @@ static int init_server_components() opt_error_log= 0; // Too long file name else { + my_bool res; #ifndef EMBEDDED_LIBRARY - if (freopen(log_error_file, "a+", stdout)) + res= reopen_fstreams(log_error_file, stdout, stderr); +#else + res= reopen_fstreams(log_error_file, NULL, stderr); #endif - { - if (freopen(log_error_file, "a+", stderr)) - setbuf(stderr, NULL); - } + + if (!res) + setbuf(stderr, NULL); } } @@ -4353,23 +4360,6 @@ int mysqld_main(int argc, char **argv) } #endif -#ifdef __WIN__ - /* - Before performing any socket operation (like retrieving hostname - in init_common_variables we have to call WSAStartup - */ - { - WSADATA WsaData; - if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData)) - { - /* errors are not read yet, so we use english text here */ - my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0)); - /* Not enough initializations for unireg_abort() */ - return 1; - } - } -#endif /* __WIN__ */ - if (init_common_variables()) unireg_abort(1); // Will do exit @@ -4457,8 +4447,8 @@ int mysqld_main(int argc, char **argv) #ifdef __WIN__ if (!opt_console) { - freopen(log_error_file,"a+",stdout); - freopen(log_error_file,"a+",stderr); + if (reopen_fstreams(log_error_file, stdout, stderr)) + unireg_abort(1); setbuf(stderr, NULL); FreeConsole(); // Remove window } @@ -5028,7 +5018,7 @@ static void create_new_thread(THD *thd) thread_count++; - thread_scheduler.add_connection(thd); + MYSQL_CALLBACK(thread_scheduler, add_connection, (thd)); DBUG_VOID_RETURN; } @@ -7344,14 +7334,12 @@ static int get_options(int *argc_ptr, ch return 1; #ifdef EMBEDDED_LIBRARY - one_thread_scheduler(&thread_scheduler); + one_thread_scheduler(); #else if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION) - one_thread_per_connection_scheduler(&thread_scheduler); - else if (thread_handling == SCHEDULER_NO_THREADS) - one_thread_scheduler(&thread_scheduler); - else - pool_of_threads_scheduler(&thread_scheduler); /* purecov: tested */ + one_thread_per_connection_scheduler(); + else /* thread_handling == SCHEDULER_NO_THREADS) */ + one_thread_scheduler(); #endif global_system_variables.engine_condition_pushdown= === modified file 'sql/mysqld.h' --- a/sql/mysqld.h 2010-08-18 11:29:04 +0000 +++ b/sql/mysqld.h 2010-08-30 14:07:40 +0000 @@ -28,7 +28,7 @@ class THD; struct handlerton; class Time_zone; -class scheduler_functions; +struct scheduler_functions; typedef struct st_mysql_const_lex_string LEX_CSTRING; typedef struct st_mysql_show_var SHOW_VAR; @@ -175,7 +175,7 @@ extern ulong binlog_cache_size, open_fil extern ulonglong max_binlog_cache_size; extern ulong max_binlog_size, max_relay_log_size; extern ulong opt_binlog_rows_event_max_size; -extern ulong rpl_recovery_rank, thread_cache_size, thread_pool_size; +extern ulong rpl_recovery_rank, thread_cache_size; extern ulong back_log; extern char language[FN_REFLEN]; extern ulong server_id, concurrency; @@ -207,7 +207,7 @@ extern my_bool old_mode; extern LEX_STRING opt_init_connect, opt_init_slave; extern int bootstrap_error; extern I_List threads; -extern scheduler_functions thread_scheduler; +extern char err_shared_dir[]; extern TYPELIB thread_handling_typelib; extern my_decimal decimal_zero; === modified file 'sql/opt_range.cc' --- a/sql/opt_range.cc 2010-07-15 13:47:50 +0000 +++ b/sql/opt_range.cc 2010-08-26 12:35:38 +0000 @@ -5620,7 +5620,11 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_P SEL_TREE *tmp= get_full_func_mm_tree(param, cond_func, field_item, (Item*)(intptr)i, inv); if (inv) + { tree= !tree ? tmp : tree_or(param, tree, tmp); + if (tree == NULL) + break; + } else tree= tree_and(param, tree, tmp); } === modified file 'sql/scheduler.cc' --- a/sql/scheduler.cc 2010-03-31 14:05:33 +0000 +++ b/sql/scheduler.cc 2010-06-15 07:44:26 +0000 @@ -25,55 +25,103 @@ #include "unireg.h" // REQUIRED: for other includes #include "scheduler.h" #include "sql_connect.h" // init_new_connection_handler_thread +#include "scheduler.h" +#include "sql_callback.h" /* - 'Dummy' functions to be used when we don't need any handling for a scheduler - event - */ + End connection, in case when we are using 'no-threads' +*/ -static bool init_dummy(void) {return 0;} -static void post_kill_dummy(THD* thd) {} -static void end_dummy(void) {} -static bool end_thread_dummy(THD *thd, bool cache_thread) { return 0; } +static bool no_threads_end(THD *thd, bool put_in_cache) +{ + unlink_thd(thd); + mysql_mutex_unlock(&LOCK_thread_count); + return 1; // Abort handle_one_connection +} -/* - Initialize default scheduler with dummy functions so that setup functions - only need to declare those that are relvant for their usage +static scheduler_functions one_thread_scheduler_functions= +{ + 1, // max_threads + NULL, // init + init_new_connection_handler_thread, // init_new_connection_thread +#ifndef EMBEDDED_LIBRARY + handle_connection_in_main_thread, // add_connection +#else + NULL, // add_connection +#endif // EMBEDDED_LIBRARY + NULL, // thd_wait_begin + NULL, // thd_wait_end + NULL, // post_kill_notification + no_threads_end, // end_thread + NULL, // end +}; + +#ifndef EMBEDDED_LIBRARY +static scheduler_functions one_thread_per_connection_scheduler_functions= +{ + 0, // max_threads + NULL, // init + init_new_connection_handler_thread, // init_new_connection_thread + create_thread_to_handle_connection, // add_connection + NULL, // thd_wait_begin + NULL, // thd_wait_end + NULL, // post_kill_notification + one_thread_per_connection_end, // end_thread + NULL, // end +}; +#endif // EMBEDDED_LIBRARY + + +scheduler_functions *thread_scheduler= NULL; + +/** @internal + Helper functions to allow mysys to call the thread scheduler when + waiting for locks. */ -scheduler_functions::scheduler_functions() - :init(init_dummy), - init_new_connection_thread(init_new_connection_handler_thread), - add_connection(0), // Must be defined - post_kill_notification(post_kill_dummy), - end_thread(end_thread_dummy), end(end_dummy) -{} +/**@{*/ +static void scheduler_wait_begin(void) { + MYSQL_CALLBACK(thread_scheduler, + thd_wait_begin, (current_thd, THD_WAIT_ROW_TABLE_LOCK)); +} + +static void scheduler_wait_end(void) { + MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (current_thd)); +} +/**@}*/ +/** + Common scheduler init function. + + The scheduler is either initialized by calling + one_thread_scheduler() or one_thread_per_connection_scheduler() in + mysqld.cc, so this init function will always be called. + */ +static void scheduler_init() { + thr_set_lock_wait_callback(scheduler_wait_begin, scheduler_wait_end); +} /* - End connection, in case when we are using 'no-threads' + Initialize scheduler for --thread-handling=one-thread-per-connection */ -static bool no_threads_end(THD *thd, bool put_in_cache) +#ifndef EMBEDDED_LIBRARY +void one_thread_per_connection_scheduler() { - unlink_thd(thd); - mysql_mutex_unlock(&LOCK_thread_count); - return 1; // Abort handle_one_connection + scheduler_init(); + one_thread_per_connection_scheduler_functions.max_threads= max_connections; + thread_scheduler= &one_thread_per_connection_scheduler_functions; } - +#endif /* Initailize scheduler for --thread-handling=no-threads */ -void one_thread_scheduler(scheduler_functions* func) +void one_thread_scheduler() { - func->max_threads= 1; -#ifndef EMBEDDED_LIBRARY - func->add_connection= handle_connection_in_main_thread; -#endif - func->init_new_connection_thread= init_dummy; - func->end_thread= no_threads_end; + scheduler_init(); + thread_scheduler= &one_thread_scheduler_functions; } @@ -81,11 +129,58 @@ void one_thread_scheduler(scheduler_func Initialize scheduler for --thread-handling=one-thread-per-connection */ -#ifndef EMBEDDED_LIBRARY -void one_thread_per_connection_scheduler(scheduler_functions* func) +/* + thd_scheduler keeps the link between THD and events. + It's embedded in the THD class. +*/ + +thd_scheduler::thd_scheduler() + : m_psi(NULL), data(NULL) +{ +#ifndef DBUG_OFF + dbug_explain[0]= '\0'; + set_explain= FALSE; +#endif +} + + +thd_scheduler::~thd_scheduler() +{ +} + +static scheduler_functions *saved_thread_scheduler; +static uint saved_thread_handling; + +extern "C" +int my_thread_scheduler_set(scheduler_functions *scheduler) +{ + DBUG_ASSERT(scheduler != 0); + + if (scheduler == NULL) + return 1; + + saved_thread_scheduler= thread_scheduler; + saved_thread_handling= thread_handling; + thread_scheduler= scheduler; + // Scheduler loaded dynamically + thread_handling= SCHEDULER_TYPES_COUNT; + return 0; +} + + +extern "C" +int my_thread_scheduler_reset() { - func->max_threads= max_connections; - func->add_connection= create_thread_to_handle_connection; - func->end_thread= one_thread_per_connection_end; + DBUG_ASSERT(saved_thread_scheduler != NULL); + + if (saved_thread_scheduler == NULL) + return 1; + + thread_scheduler= saved_thread_scheduler; + thread_handling= saved_thread_handling; + saved_thread_scheduler= 0; + return 0; } -#endif /* EMBEDDED_LIBRARY */ + + + === modified file 'sql/scheduler.h' --- a/sql/scheduler.h 2009-09-23 21:32:31 +0000 +++ b/sql/scheduler.h 2010-06-07 14:01:39 +0000 @@ -28,38 +28,77 @@ class THD; /* Functions used when manipulating threads */ -class scheduler_functions +struct scheduler_functions { -public: uint max_threads; bool (*init)(void); bool (*init_new_connection_thread)(void); void (*add_connection)(THD *thd); + void (*thd_wait_begin)(THD *thd, int wait_type); + void (*thd_wait_end)(THD *thd); void (*post_kill_notification)(THD *thd); bool (*end_thread)(THD *thd, bool cache_thread); void (*end)(void); - scheduler_functions(); }; + +/** + Scheduler types enumeration. + + The default of --thread-handling is the first one in the + thread_handling_names array, this array has to be consistent with + the order in this array, so to change default one has to change the + first entry in this enum and the first entry in the + thread_handling_names array. + + @note The last entry of the enumeration is also used to mark the + thread handling as dynamic. In this case the name of the thread + handling is fetched from the name of the plugin that implements it. +*/ enum scheduler_types { SCHEDULER_ONE_THREAD_PER_CONNECTION=0, SCHEDULER_NO_THREADS, - SCHEDULER_POOL_OF_THREADS + SCHEDULER_TYPES_COUNT }; -void one_thread_per_connection_scheduler(scheduler_functions* func); -void one_thread_scheduler(scheduler_functions* func); +void one_thread_per_connection_scheduler(); +void one_thread_scheduler(); enum pool_command_op { NOT_IN_USE_OP= 0, NORMAL_OP= 1, CONNECT_OP, KILL_OP, DIE_OP }; -#define HAVE_POOL_OF_THREADS 0 /* For easyer tests */ -#define pool_of_threads_scheduler(A) one_thread_per_connection_scheduler(A) - +/* + To be used for pool-of-threads (implemeneted differently on various OSs) +*/ class thd_scheduler -{}; +{ +public: + /* + Thread instrumentation for the user job. + This member holds the instrumentation while the user job is not run + by a thread. + + Note that this member is not conditionally declared + (ifdef HAVE_PSI_INTERFACE), because doing so will change the binary + layout of THD, which is exposed to plugin code that may be compiled + differently. + */ + PSI_thread *m_psi; + + void *data; /* scheduler-specific data structure */ + +# ifndef DBUG_OFF + char dbug_explain[512]; + bool set_explain; +# endif + + thd_scheduler(); + ~thd_scheduler(); +}; + +extern scheduler_functions *thread_scheduler; -#endif /* SCHEDULER_INCLUDED */ +#endif === added file 'sql/sql_callback.h' --- a/sql/sql_callback.h 1970-01-01 00:00:00 +0000 +++ b/sql/sql_callback.h 2010-06-07 14:01:39 +0000 @@ -0,0 +1,43 @@ +/* + Copyright (C) 2010, Oracle and/or its affiliates. All rights reserved. + + 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 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 +*/ + +#ifndef SQL_CALLBACK_INCLUDED +#define SQL_CALLBACK_INCLUDED + +/** + Macro used for an internal callback. + + The macro will check that the object exists and that the function + is defined. If that is the case, it will call the function with the + given parameters. + + If the object or the function is not defined, the callback will be + considered successful (nothing needed to be done) and will + therefore return no error. + */ + +#define MYSQL_CALLBACK(OBJ, FUNC, PARAMS) \ + do { \ + if ((OBJ) && ((OBJ)->FUNC)) \ + (OBJ)->FUNC PARAMS; \ + } while (0) + +#define MYSQL_CALLBACK_ELSE(OBJ, FUNC, PARAMS, ELSE) \ + (((OBJ) && ((OBJ)->FUNC)) ? (OBJ)->FUNC PARAMS : (ELSE)) + + +#endif /* SQL_CALLBACK_INCLUDED */ === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2010-08-20 02:59:58 +0000 +++ b/sql/sql_class.cc 2010-08-30 14:07:40 +0000 @@ -57,6 +57,7 @@ #include "transaction.h" #include "debug_sync.h" #include "sql_parse.h" // is_update_query +#include "sql_callback.h" /* The following is used to initialise Table_ident with a internal @@ -1075,6 +1076,7 @@ THD::~THD() DBUG_ENTER("~THD()"); /* Ensure that no one is using THD */ mysql_mutex_lock(&LOCK_thd_data); + mysys_var=0; // Safety (shouldn't be needed) mysql_mutex_unlock(&LOCK_thd_data); add_to_status(&global_status_var, &status_var); @@ -1100,7 +1102,6 @@ THD::~THD() my_free(db); db= NULL; free_root(&transaction.mem_root,MYF(0)); - mysys_var=0; // Safety (shouldn't be needed) mysql_mutex_destroy(&LOCK_thd_data); #ifndef DBUG_OFF dbug_sentry= THD_SENTRY_GONE; @@ -1189,7 +1190,7 @@ void THD::awake(THD::killed_state state_ { thr_alarm_kill(thread_id); if (!slave_thread) - thread_scheduler.post_kill_notification(this); + MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (this)); #ifdef SIGNAL_WITH_VIO_CLOSE if (this != current_thd) { @@ -1258,6 +1259,15 @@ bool THD::store_globals() if (my_pthread_setspecific_ptr(THR_THD, this) || my_pthread_setspecific_ptr(THR_MALLOC, &mem_root)) return 1; + /* + mysys_var is concurrently readable by a killer thread. + It is protected by LOCK_thd_data, it is not needed to lock while the + pointer is changing from NULL not non-NULL. If the kill thread reads + NULL it doesn't refer to anything, but if it is non-NULL we need to + ensure that the thread doesn't proceed to assign another thread to + have the mysys_var reference (which in fact refers to the worker + threads local storage with key THR_KEY_mysys. + */ mysys_var=my_thread_var; /* Let mysqld define the thread id (not mysys) @@ -3187,6 +3197,60 @@ extern "C" bool thd_sqlcom_can_generate_ { return sqlcom_can_generate_row_events(thd); } + +#ifndef EMBEDDED_LIBRARY +extern "C" void thd_pool_wait_begin(MYSQL_THD thd, int wait_type); +extern "C" void thd_pool_wait_end(MYSQL_THD thd); + +/* + Interface for MySQL Server, plugins and storage engines to report + when they are going to sleep/stall. + + SYNOPSIS + thd_wait_begin() + thd Thread object + wait_type Type of wait + 1 -- short wait (e.g. for mutex) + 2 -- medium wait (e.g. for disk io) + 3 -- large wait (e.g. for locked row/table) + NOTES + This is used by the threadpool to have better knowledge of which + threads that currently are actively running on CPUs. When a thread + reports that it's going to sleep/stall, the threadpool scheduler is + free to start another thread in the pool most likely. The expected wait + time is simply an indication of how long the wait is expected to + become, the real wait time could be very different. + + thd_wait_end MUST be called immediately after waking up again. +*/ +extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type) +{ + MYSQL_CALLBACK(thread_scheduler, thd_wait_begin, (thd, wait_type)); +} + +/** + Interface for MySQL Server, plugins and storage engines to report + when they waking up from a sleep/stall. + + @param thd Thread handle +*/ +extern "C" void thd_wait_end(MYSQL_THD thd) +{ + MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (thd)); +} +#else +extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type) +{ + /* do NOTHING for the embedded library */ + return; +} + +extern "C" void thd_wait_end(MYSQL_THD thd) +{ + /* do NOTHING for the embedded library */ + return; +} +#endif #endif // INNODB_COMPATIBILITY_HOOKS */ /**************************************************************************** @@ -3370,6 +3434,13 @@ void THD::set_query_id(query_id_t new_qu mysql_mutex_unlock(&LOCK_thd_data); } +/** Assign a new value to thd->mysys_var. */ +void THD::set_mysys_var(struct st_my_thread_var *new_mysys_var) +{ + mysql_mutex_lock(&LOCK_thd_data); + mysys_var= new_mysys_var; + mysql_mutex_unlock(&LOCK_thd_data); +} /** Leave explicit LOCK TABLES or prelocked mode and restore value of === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2010-08-25 10:22:34 +0000 +++ b/sql/sql_class.h 2010-08-30 14:07:40 +0000 @@ -1634,6 +1634,10 @@ public: xid_state.xid.null(); free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); } + my_bool is_active() + { + return (all.ha_list != NULL); + } st_transactions() { bzero((char*)this, sizeof(*this)); @@ -2664,7 +2668,7 @@ public: virtual void set_statement(Statement *stmt); /** - Assign a new value to thd->query and thd->query_id. + Assign a new value to thd->query and thd->query_id and mysys_var. Protected with LOCK_thd_data mutex. */ void set_query(char *query_arg, uint32 query_length_arg); @@ -2677,6 +2681,7 @@ public: open_tables= open_tables_arg; mysql_mutex_unlock(&LOCK_thd_data); } + void set_mysys_var(struct st_my_thread_var *new_mysys_var); void enter_locked_tables_mode(enum_locked_tables_mode mode_arg) { DBUG_ASSERT(locked_tables_mode == LTM_NONE); === modified file 'sql/sql_connect.cc' --- a/sql/sql_connect.cc 2010-08-05 12:53:09 +0000 +++ b/sql/sql_connect.cc 2010-08-16 12:50:27 +0000 @@ -35,6 +35,7 @@ #include "hostname.h" // inc_host_errors, ip_to_hostname, // reset_host_errors #include "sql_acl.h" // acl_getroot, NO_ACCESS, SUPER_ACL +#include "sql_callback.h" #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) /* @@ -966,7 +967,7 @@ bool setup_connection_thread_globals(THD { close_connection(thd, ER_OUT_OF_RESOURCES, 1); statistic_increment(aborted_connects,&LOCK_status); - thread_scheduler.end_thread(thd, 0); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); return 1; // Error } return 0; @@ -989,7 +990,7 @@ bool setup_connection_thread_globals(THD */ -static bool login_connection(THD *thd) +bool login_connection(THD *thd) { NET *net= &thd->net; int error; @@ -1027,7 +1028,7 @@ static bool login_connection(THD *thd) This mainly updates status variables */ -static void end_connection(THD *thd) +void end_connection(THD *thd) { NET *net= &thd->net; plugin_thdvar_cleanup(thd); @@ -1068,7 +1069,7 @@ static void end_connection(THD *thd) Initialize THD to handle queries */ -static void prepare_new_connection_state(THD* thd) +void prepare_new_connection_state(THD* thd) { Security_context *sctx= thd->security_ctx; @@ -1137,11 +1138,11 @@ void do_handle_one_connection(THD *thd_a thd->thr_create_utime= my_micro_time(); - if (thread_scheduler.init_new_connection_thread()) + if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0)) { close_connection(thd, ER_OUT_OF_RESOURCES, 1); statistic_increment(aborted_connects,&LOCK_status); - thread_scheduler.end_thread(thd,0); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); return; } @@ -1195,7 +1196,7 @@ void do_handle_one_connection(THD *thd_a end_thread: close_connection(thd, 0, 1); - if (thread_scheduler.end_thread(thd,1)) + if (MYSQL_CALLBACK_ELSE(thread_scheduler, end_thread, (thd, 1), 0)) return; // Probably no-threads /* === modified file 'sql/sql_connect.h' --- a/sql/sql_connect.h 2010-03-31 14:05:33 +0000 +++ b/sql/sql_connect.h 2010-06-07 14:01:39 +0000 @@ -40,4 +40,8 @@ int check_user(THD *thd, enum enum_serve const char *passwd, uint passwd_len, const char *db, bool check_count); +bool login_connection(THD *thd); +void prepare_new_connection_state(THD* thd); +void end_connection(THD *thd); + #endif /* SQL_CONNECT_INCLUDED */ === modified file 'sql/sql_plugin_services.h' --- a/sql/sql_plugin_services.h 2009-11-02 20:05:42 +0000 +++ b/sql/sql_plugin_services.h 2010-06-07 14:01:39 +0000 @@ -36,9 +36,23 @@ static struct thd_alloc_service_st thd_a thd_make_lex_string }; +static struct thd_wait_service_st thd_wait_handler= { + thd_wait_begin, + thd_wait_end +}; + +static struct my_thread_scheduler_service my_thread_scheduler_handler= { + my_thread_scheduler_set, + my_thread_scheduler_reset, +}; + + static struct st_service_ref list_of_services[]= { { "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler }, - { "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler } + { "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler }, + { "thd_wait_service", VERSION_thd_wait, &thd_wait_handler }, + { "my_thread_scheduler_service", + VERSION_my_thread_scheduler, &my_thread_scheduler_handler }, }; === modified file 'sql/sql_select.cc' --- a/sql/sql_select.cc 2010-08-17 12:12:52 +0000 +++ b/sql/sql_select.cc 2010-08-27 11:33:32 +0000 @@ -13243,6 +13243,34 @@ ok: } +/** + Find shortest key suitable for full table scan. + + @param table Table to scan + @param usable_keys Allowed keys + + @note + As far as + 1) clustered primary key entry data set is a set of all record + fields (key fields and not key fields) and + 2) secondary index entry data is a union of its key fields and + primary key fields (at least InnoDB and its derivatives don't + duplicate primary key fields there, even if the primary and + the secondary keys have a common subset of key fields), + then secondary index entry data is always a subset of primary key entry. + Unfortunately, key_info[nr].key_length doesn't show the length + of key/pointer pair but a sum of key field lengths only, thus + we can't estimate index IO volume comparing only this key_length + value of secondary keys and clustered PK. + So, try secondary keys first, and choose PK only if there are no + usable secondary covering keys or found best secondary key include + all table fields (i.e. same as PK): + + @return + MAX_KEY no suitable key found + key index otherwise +*/ + uint find_shortest_key(TABLE *table, const key_map *usable_keys) { uint best= MAX_KEY; @@ -13255,23 +13283,6 @@ uint find_shortest_key(TABLE *table, con uint min_length= (uint) ~0; for (uint nr=0; nr < table->s->keys ; nr++) { - /* - As far as - 1) clustered primary key entry data set is a set of all record - fields (key fields and not key fields) and - 2) secondary index entry data is a union of its key fields and - primary key fields (at least InnoDB and its derivatives don't - duplicate primary key fields there, even if the primary and - the secondary keys have a common subset of key fields), - then secondary index entry data is always a subset of primary key - entry, and the PK is always longer. - Unfortunately, key_info[nr].key_length doesn't show the length - of key/pointer pair but a sum of key field lengths only, thus - we can't estimate index IO volume comparing only this key_length - value of seconday keys and clustered PK. - So, try secondary keys first, and choose PK only if there are no - usable secondary covering keys: - */ if (nr == usable_clustered_pk) continue; if (usable_keys->is_set(nr)) @@ -13284,7 +13295,20 @@ uint find_shortest_key(TABLE *table, con } } } - return best != MAX_KEY ? best : usable_clustered_pk; + if (usable_clustered_pk != MAX_KEY) + { + /* + If the primary key is clustered and found shorter key covers all table + fields then primary key scan normally would be faster because amount of + data to scan is the same but PK is clustered. + It's safe to compare key parts with table fields since duplicate key + parts aren't allowed. + */ + if (best == MAX_KEY || + table->key_info[best].key_parts >= table->s->fields) + best= usable_clustered_pk; + } + return best; } /** === modified file 'sql/sql_show.cc' --- a/sql/sql_show.cc 2010-08-18 11:29:04 +0000 +++ b/sql/sql_show.cc 2010-08-30 14:07:40 +0000 @@ -1815,6 +1815,7 @@ void mysqld_list_processes(THD *thd,cons if ((thd_info->db=tmp->db)) // Safe test thd_info->db=thd->strdup(thd_info->db); thd_info->command=(int) tmp->command; + mysql_mutex_lock(&tmp->LOCK_thd_data); if ((mysys_var= tmp->mysys_var)) mysql_mutex_lock(&mysys_var->mutex); thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0); @@ -1822,16 +1823,15 @@ void mysqld_list_processes(THD *thd,cons if (mysys_var) mysql_mutex_unlock(&mysys_var->mutex); - thd_info->start_time= tmp->start_time; thd_info->query=0; /* Lock THD mutex that protects its data when looking at it. */ - mysql_mutex_lock(&tmp->LOCK_thd_data); if (tmp->query()) { uint length= min(max_query_length, tmp->query_length()); thd_info->query= (char*) thd->strmake(tmp->query(),length); } mysql_mutex_unlock(&tmp->LOCK_thd_data); + thd_info->start_time= tmp->start_time; thread_infos.append(thd_info); } } @@ -1918,6 +1918,7 @@ int fill_schema_processlist(THD* thd, TA table->field[3]->set_notnull(); } + mysql_mutex_lock(&tmp->LOCK_thd_data); if ((mysys_var= tmp->mysys_var)) mysql_mutex_lock(&mysys_var->mutex); /* COMMAND */ @@ -1938,6 +1939,7 @@ int fill_schema_processlist(THD* thd, TA if (mysys_var) mysql_mutex_unlock(&mysys_var->mutex); + mysql_mutex_unlock(&tmp->LOCK_thd_data); /* INFO */ /* Lock THD mutex that protects its data when looking at it. */ @@ -7490,13 +7492,16 @@ int finalize_schema_table(st_plugin_int ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data; DBUG_ENTER("finalize_schema_table"); - if (schema_table && plugin->plugin->deinit) + if (schema_table) { - DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str)); - if (plugin->plugin->deinit(NULL)) + if (plugin->plugin->deinit) { - DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.", - plugin->name.str)); + DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str)); + if (plugin->plugin->deinit(NULL)) + { + DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.", + plugin->name.str)); + } } my_free(schema_table); } === modified file 'sql/sql_yacc.yy' --- a/sql/sql_yacc.yy 2010-08-25 10:22:34 +0000 +++ b/sql/sql_yacc.yy 2010-08-30 22:22:01 +0000 @@ -1425,6 +1425,7 @@ bool my_yyoverflow(short **a, YYSTYPE ** %type table_ident table_ident_nodb references xid + table_ident_opt_wild %type remember_name remember_end opt_db text_or_password @@ -10371,7 +10372,7 @@ table_alias_ref_list: ; table_alias_ref: - table_ident + table_ident_opt_wild { if (!Select->add_table_to_list(YYTHD, $1, NULL, TL_OPTION_UPDATING | TL_OPTION_ALIAS, @@ -12159,6 +12160,21 @@ table_ident: if ($$ == NULL) MYSQL_YYABORT; } + ; + +table_ident_opt_wild: + ident opt_wild + { + $$= new Table_ident($1); + if ($$ == NULL) + MYSQL_YYABORT; + } + | ident '.' ident opt_wild + { + $$= new Table_ident(YYTHD, $1,$3,0); + if ($$ == NULL) + MYSQL_YYABORT; + } ; table_ident_nodb: === modified file 'sql/sys_vars.cc' --- a/sql/sys_vars.cc 2010-08-25 00:21:43 +0000 +++ b/sql/sys_vars.cc 2010-08-30 14:07:40 +0000 @@ -1673,19 +1673,13 @@ static Sys_var_ulong Sys_trans_prealloc_ static const char *thread_handling_names[]= { - "one-thread-per-connection", "no-threads", -#if HAVE_POOL_OF_THREADS == 1 - "pool-of-threads", -#endif + "one-thread-per-connection", "no-threads", "loaded-dynamically", 0 }; static Sys_var_enum Sys_thread_handling( "thread_handling", "Define threads usage for handling queries, one of " - "one-thread-per-connection, no-threads" -#if HAVE_POOL_OF_THREADS == 1 - ", pool-of-threads" -#endif + "one-thread-per-connection, no-threads, loaded-dynamically" , READ_ONLY GLOBAL_VAR(thread_handling), CMD_LINE(REQUIRED_ARG), thread_handling_names, DEFAULT(0)); === modified file 'storage/innobase/buf/buf0flu.c' --- a/storage/innobase/buf/buf0flu.c 2010-07-30 14:39:16 +0000 +++ b/storage/innobase/buf/buf0flu.c 2010-08-30 14:07:40 +0000 @@ -43,6 +43,8 @@ Created 11/11/1995 Heikki Tuuri #include "log0log.h" #include "os0file.h" #include "trx0sys.h" +#include "mysql/plugin.h" +#include "mysql/service_thd_wait.h" /********************************************************************** These statistics are generated for heuristics used in estimating the @@ -1744,10 +1746,14 @@ buf_flush_wait_batch_end( buf_pool = buf_pool_from_array(i); + thd_wait_begin(NULL, THD_WAIT_DISKIO); os_event_wait(buf_pool->no_flush[type]); + thd_wait_end(NULL); } } else { + thd_wait_begin(NULL, THD_WAIT_DISKIO); os_event_wait(buf_pool->no_flush[type]); + thd_wait_end(NULL); } } === modified file 'storage/innobase/buf/buf0rea.c' --- a/storage/innobase/buf/buf0rea.c 2010-06-22 15:58:28 +0000 +++ b/storage/innobase/buf/buf0rea.c 2010-08-16 12:50:27 +0000 @@ -37,6 +37,8 @@ Created 11/5/1995 Heikki Tuuri #include "os0file.h" #include "srv0start.h" #include "srv0srv.h" +#include "mysql/plugin.h" +#include "mysql/service_thd_wait.h" /** The linear read-ahead area size */ #define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA @@ -135,6 +137,7 @@ buf_read_page_low( ut_ad(buf_page_in_file(bpage)); + thd_wait_begin(NULL, THD_WAIT_DISKIO); if (zip_size) { *err = fil_io(OS_FILE_READ | wake_later, sync, space, zip_size, offset, 0, zip_size, @@ -146,6 +149,7 @@ buf_read_page_low( sync, space, 0, offset, 0, UNIV_PAGE_SIZE, ((buf_block_t*) bpage)->frame, bpage); } + thd_wait_end(NULL); ut_a(*err == DB_SUCCESS); if (sync) { === modified file 'storage/innobase/srv/srv0srv.c' --- a/storage/innobase/srv/srv0srv.c 2010-08-17 08:19:24 +0000 +++ b/storage/innobase/srv/srv0srv.c 2010-08-30 14:07:40 +0000 @@ -84,6 +84,8 @@ Created 10/8/1995 Heikki Tuuri #include "ha_prototypes.h" #include "trx0i_s.h" #include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */ +#include "mysql/plugin.h" +#include "mysql/service_thd_wait.h" /* This is set to TRUE if the MySQL user has set it in MySQL; currently affects only FOREIGN KEY definition parsing */ @@ -1232,7 +1234,9 @@ retry: trx->op_info = "waiting in InnoDB queue"; + thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK); os_event_wait(slot->event); + thd_wait_end(trx->mysql_thd); trx->op_info = ""; @@ -1597,7 +1601,9 @@ srv_suspend_mysql_thread( /* Suspend this thread and wait for the event. */ + thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_TABLE_LOCK); os_event_wait(event); + thd_wait_end(trx->mysql_thd); /* After resuming, reacquire the data dictionary latch if necessary. */ === modified file 'vio/vio.c' --- a/vio/vio.c 2010-07-08 21:20:08 +0000 +++ b/vio/vio.c 2010-08-16 12:50:27 +0000 @@ -44,6 +44,11 @@ static my_bool no_poll_read(Vio *vio __a #endif +static my_bool has_no_data(Vio *vio __attribute__((unused))) +{ + return FALSE; +} + /* * Helper to fill most of the Vio* with defaults. */ @@ -83,6 +88,7 @@ static void vio_init(Vio* vio, enum enum vio->poll_read =no_poll_read; vio->is_connected =vio_is_connected_pipe; + vio->has_data =has_no_data; vio->timeout=vio_win32_timeout; /* Set default timeout */ @@ -110,6 +116,7 @@ static void vio_init(Vio* vio, enum enum vio->poll_read =no_poll_read; vio->is_connected =vio_is_connected_shared_memory; + vio->has_data =has_no_data; /* Currently, shared memory is on Windows only, hence the below is ok*/ vio->timeout= vio_win32_timeout; @@ -137,6 +144,7 @@ static void vio_init(Vio* vio, enum enum vio->timeout =vio_timeout; vio->poll_read =vio_poll_read; vio->is_connected =vio_is_connected; + vio->has_data =vio_ssl_has_data; DBUG_VOID_RETURN; } #endif /* HAVE_OPENSSL */ @@ -155,6 +163,8 @@ static void vio_init(Vio* vio, enum enum vio->timeout =vio_timeout; vio->poll_read =vio_poll_read; vio->is_connected =vio_is_connected; + vio->has_data= (flags & VIO_BUFFERED_READ) ? + vio_buff_has_data : has_no_data; DBUG_VOID_RETURN; } === modified file 'vio/vio_priv.h' --- a/vio/vio_priv.h 2009-12-16 08:33:54 +0000 +++ b/vio/vio_priv.h 2010-06-07 14:01:39 +0000 @@ -49,6 +49,7 @@ int vio_close_shared_memory(Vio * vio); #endif void vio_timeout(Vio *vio,uint which, uint timeout); +my_bool vio_buff_has_data(Vio *vio); #ifdef HAVE_OPENSSL #include "my_net.h" /* needed because of struct in_addr */ @@ -62,5 +63,7 @@ void vio_ssl_delete(Vio *vio); int vio_ssl_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode); +my_bool vio_ssl_has_data(Vio *vio); + #endif /* HAVE_OPENSSL */ #endif /* VIO_PRIV_INCLUDED */ === modified file 'vio/viosocket.c' --- a/vio/viosocket.c 2010-05-21 13:17:01 +0000 +++ b/vio/viosocket.c 2010-08-16 12:50:27 +0000 @@ -98,6 +98,10 @@ size_t vio_read_buff(Vio *vio, uchar* bu #undef VIO_UNBUFFERED_READ_MIN_SIZE } +my_bool vio_buff_has_data(Vio *vio) +{ + return (vio->read_pos != vio->read_end); +} size_t vio_write(Vio * vio, const uchar* buf, size_t size) { === modified file 'vio/viossl.c' --- a/vio/viossl.c 2010-07-15 11:13:30 +0000 +++ b/vio/viossl.c 2010-08-16 12:50:27 +0000 @@ -244,6 +244,9 @@ int vio_ssl_blocking(Vio *vio __attribut return (set_blocking_mode ? 0 : 1); } - +my_bool vio_ssl_has_data(Vio *vio) +{ + return SSL_pending(vio->ssl_arg) > 0 ? TRUE : FALSE; +} #endif /* HAVE_OPENSSL */ --===============1787014902== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/bjorn.munch@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: bjorn.munch@stripped # target_branch: file:///home/bm136801/my/mtr-55/ # testament_sha1: a9c6a521f507514eb04bf6eeaeee1b8d2405bd70 # timestamp: 2010-09-02 10:18:06 +0200 # source_branch: file:///home/bm136801/my/mysql-5.5/ # base_revision_id: bjorn.munch@stripped\ # 1fnvzg7oldv64ia9 # # Begin bundle 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 LD9N//i7kinChIOvBfkI --===============1787014902==--