diff --git a/include/mysql.h b/include/mysql.h index ff914037eaf..12c55edd6f5 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -384,8 +384,8 @@ int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB); */ int simple_command(MYSQL *mysql,enum enum_server_command command, - const char *arg, ulong length, my_bool skipp_check); -ulong net_safe_read(MYSQL* mysql); + const char *arg, unsigned long length, my_bool skipp_check); +unsigned long net_safe_read(MYSQL* mysql); #ifdef __cplusplus } diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index a9044609df4..ffc07784b7a 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -236,13 +236,13 @@ done MYRUN_DIR=$MYSQL_TEST_DIR/var/run MASTER_MYDDIR="$MYSQL_TEST_DIR/var/master-data" -MASTER_MYSOCK="$MYSQL_TMP_DIR/mysql-master.sock" +MASTER_MYSOCK="$MYSQL_TMP_DIR/master.sock" MASTER_MYPID="$MYRUN_DIR/mysqld.pid" MASTER_MYLOG="$MYSQL_TEST_DIR/var/log/mysqld.log" MASTER_MYERR="$MYSQL_TEST_DIR/var/log/mysqld.err" SLAVE_MYDDIR="$MYSQL_TEST_DIR/var/slave-data" -SLAVE_MYSOCK="$MYSQL_TMP_DIR/mysql-slave.sock" +SLAVE_MYSOCK="$MYSQL_TMP_DIR/slave.sock" SLAVE_MYPID="$MYRUN_DIR/mysqld-slave.pid" SLAVE_MYLOG="$MYSQL_TEST_DIR/var/log/mysqld-slave.log" SLAVE_MYERR="$MYSQL_TEST_DIR/var/log/mysqld-slave.err" diff --git a/scripts/explain_log.sh b/scripts/explain_log.sh new file mode 100644 index 00000000000..d7f6bb97b40 --- /dev/null +++ b/scripts/explain_log.sh @@ -0,0 +1,383 @@ +#!@PERL@ -w +use strict; +use DBI; + +use Getopt::Long; +$Getopt::Long::ignorecase=0; + +print "explain_log provided by http://www.mobile.de\n"; +print "=========== ================================\n"; + +my $Param={}; + +$Param->{host}=''; +$Param->{user}=''; +$Param->{password}=''; +$Param->{PrintError}=0; + +if (!GetOptions ('date|d:i' => \$Param->{ViewDate}, + 'host|h:s' => \$Param->{host}, + 'user|u:s' => \$Param->{user}, + 'password|p:s' => \$Param->{password}, + 'printerror|e:s' => \$Param->{PrintError}, + )) { + ShowOptions(); +} +else { + $Param->{UpdateCount} = 0; + $Param->{SelectCount} = 0; + $Param->{IdxUseCount} = 0; + $Param->{LineCount} = 0; + + $Param->{Init} = 0; + $Param->{Field} = 0; + $Param->{Refresh} = 0; + $Param->{QueryCount} = 0; + $Param->{Statistics} =0; + + $Param->{Query} = undef; + $Param->{ALL} = undef ; + $Param->{Comment} = undef ; + + @{$Param->{Rows}} = (qw|possible_keys key type|); + + if ($Param->{ViewDate}) { + $Param->{View} = 0; + } + else { + $Param->{View} = 1; + } + + #print "Date=$Param->{ViewDate}, host=$Param->{host}, user=$Param->{user}, password=$Param->{password}\n"; + + $Param->{dbh}=DBI->connect("DBI:mysql:host=$Param->{host}",$Param->{user},$Param->{password},{PrintError=>0}); + if (DBI::err()) { + print "Error: " . DBI::errstr() . "\n"; + } + else { + $Param->{Start} = time; + while() { + $Param->{LineCount} ++ ; + + if ($Param->{ViewDate} ) { + if (m/^(\d{6})\s+\d{1,2}:\d\d:\d\d\s.*$/) { # get date + #print "# $1 #\n"; + if ($1 == $Param->{ViewDate}) { + $Param->{View} = 1; + } + else { + $Param->{View} = 0; + } + } + } + if ($Param->{View} ) { + #print "->>>$_"; + + if (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Connect.+\s+on\s+(.*)$/i) { # get connection ID($2) and database($3) + #print "C-$1--$2--$3------\n"; + RunQuery($Param); + if (defined $3) { + $Param->{CID}->{$2} = $3 ; + #print "DB:$Param->{CID}->{$2} .. $2 .. $3 \n"; + } + } + + elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Connect.+$/i) { # get connection ID($2) and database($3) + #print "\n <<<<<<<<<<<<<<<<<<----------------------------<<<<<<<<<<<<<<<< \n"; + #print "Connect \n"; + RunQuery($Param); + } + elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Change user .*\s+on\s+(.*)$/i) { # get connection ID($2) and database($3) + #print "C-$1--$2--$3------\n"; + RunQuery($Param); + if (defined $3) { + $Param->{CID}->{$2} = $3 ; + #print "DB:$Param->{CID}->{$2} .. $2 .. $3 \n"; + } + } + + elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Quit\s+$/i) { # remove connection ID($2) and querystring + #print "Q-$1--$2--------\n"; + RunQuery($Param); + delete $Param->{CID}->{$2} ; + } + + elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(select.+)$/i) { # get connection ID($2) and querystring + #print "S1-$1--$2--$3------\n"; + RunQuery($Param); + unless ($Param->{CID}->{$2}) { + #print "Error: No Database for Handle: $2 found\n"; + } + else { + $Param->{DB}=$Param->{CID}->{$2}; + + my $s = "$3"; + $s =~ s/from\s/from $Param->{DB}./i; + $Param->{Query}="EXPLAIN $s"; + + #$s =~ m/from\s+(\w+[.]\w+)/i; + #$Param->{tab} =$1; + #print "-- $Param->{tab} -- $s --\n"; + } + } + + elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(update.+)$/i) { # get connection ID($2) and querystring + #print "S2--$1--$2--$3------\n"; + RunQuery($Param); + unless ($Param->{CID}->{$2}) { + #print "Error: No Database for Handle: $2 found\n"; + } + else { + $Param->{DB}=$Param->{CID}->{$2}; + + my $ud = $3; + $ud =~ m/^update\s+(\w+).+(where.+)$/i; + $Param->{Query} ="EXPLAIN SELECT * FROM $1 $2"; + $Param->{Query} =~ s/from\s/from $Param->{DB}./i; + + #$Param->{Query} =~ m/from\s+(\w+[.]\w+)/i; + #$Param->{tab} =$1; + } + } + + elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Statistics\s+(.*)$/i) { # get connection ID($2) and info? + $Param->{Statistics} ++; + #print "Statistics--$1--$2--$3------\n"; + RunQuery($Param); + } + elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Query\s+(.+)$/i) { # get connection ID($2) + $Param->{QueryCount} ++; + #print "Query-NULL $3\n"; + RunQuery($Param); + } + elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Refresh\s+(.+)$/i) { # get connection ID($2) + $Param->{Refresh} ++; + #print "Refresh\n"; + RunQuery($Param); + } + elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Init\s+(.+)$/i) { # get connection ID($2) + $Param->{Init} ++; + #print "Init $3\n"; + RunQuery($Param); + } + elsif (m/^(\d{6}\s+\d{1,2}:\d\d:\d\d\s+|\s+)(\d+)\s+Field\s+(.+)$/i) { # get connection ID($2) + $Param->{Field} ++; + #print "Field $3\n"; + RunQuery($Param); + } + + elsif (m/^\s+(.+)$/ ) { # command could be some lines ... + #print "multi-lined ($1)\n"; + my ($A)=$1; + chomp $A; + $Param->{Query} .= " $1"; + #print "multi-lined ($1)<<$Param->{Query}>>\n"; + } + + + } + + } + + $Param->{dbh}->disconnect(); + + if (1 == 0) { + print "\nunclosed handles----------------------------------------\n"; + my $count=0; + foreach (sort keys %{$Param->{CID}}) { + print "$count | $_ : $Param->{CID}->{$_} \n"; + $count ++; + } + } + + print "\nIndex usage ------------------------------------\n"; + foreach my $t (sort keys %{$Param->{Data}}) { + print "\nTable\t$t: ---\n"; + foreach my $k (sort keys %{$Param->{Data}->{$t}}) { + print " count\t$k:\n"; + my %h = %{$Param->{Data}->{$t}->{$k}}; + foreach (sort {$h{$a} <=> $h{$b}} keys %h) { + print " $Param->{Data}->{$t}->{$k}->{$_}\t$_\n"; + } + } + } + + $Param->{AllCount}=0; + print "\nQueries causing table scans -------------------\n\n"; + foreach (@{$Param->{ALL}}) { + $Param->{AllCount} ++; + print "$_\n"; + } + print "Sum: $Param->{AllCount} table scans\n"; + + print "\nSummary ---------------------------------------\n\n"; + print "Select: \t$Param->{SelectCount} queries\n"; + print "Update: \t$Param->{UpdateCount} queries\n"; + print "\n"; + + print "Init: \t$Param->{Init} times\n"; + print "Field: \t$Param->{Field} times\n"; + print "Refresh: \t$Param->{Refresh} times\n"; + print "Query: \t$Param->{QueryCount} times\n"; + print "Statistics:\t$Param->{Statistics} times\n"; + print "\n"; + + print "Logfile: \t$Param->{LineCount} lines\n"; + print "Started: \t".localtime($Param->{Start})."\n"; + print "Finished: \t".localtime(time)."\n"; + + } +} + + +########################################################################### +# +# +# +sub RunQuery { + my $Param = shift ; + + if (defined $Param->{Query}) { + if (defined $Param->{DB} ) { + + $Param->{Query} =~ m/from\s+(\w+[.]\w+|\w+)/i; + $Param->{tab} =$1; + #print "||$Param->{tab} -- $Param->{Query}\n"; + + my $sth=$Param->{dbh}->prepare("USE $Param->{DB}"); + if (DBI::err()) { + if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";} + } + else { + $sth->execute(); + if (DBI::err()) { + if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";} + } + else { + $sth->finish(); + + $sth=$Param->{dbh}->prepare($Param->{Query}); + if (DBI::err()) { + if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";} + } + else { + #print "$Param->{Query}\n"; + $sth->execute(); + if (DBI::err()) { + if ($Param->{PrintError}) {print "[$Param->{LineCount}]<<$Param->{Query}>>\n";} + if ($Param->{PrintError}) {print "Error: ".DBI::errstr()."\n";} + } + else { + my $row = undef; + while ($row = $sth->fetchrow_hashref()) { + $Param->{SelectCount} ++; + + if (defined $row->{Comment}) { + push (@{$Param->{Comment}}, "$row->{Comment}; $_; $Param->{DB}; $Param->{Query}"); + } + foreach (@{$Param->{Rows}}) { + if (defined $row->{$_}) { + #if (($_ eq 'type' ) and ($row->{$_} eq 'ALL')) { + if ($row->{type} eq 'ALL') { + push (@{$Param->{ALL}}, "$row->{$_} $_ $Param->{DB} $Param->{Query}"); + #print ">> $row->{$_} $_ $Param->{DB} $Param->{Query}\n"; + } + $Param->{IdxUseCount} ++; + $Param->{Data}->{$Param->{tab}}->{$_}->{$row->{$_}} ++; + } + } + } + } + } + } + } + $sth->finish(); + } + $Param->{Query} = undef ; + } +} + +########################################################################### +# +# +# +sub ShowOptions { + print <, http://www.mobile.de + +=head1 RECRUITING + +If you are looking for a MySQL or Perl job, take a look at http://www.mobile.de +and send me an email with your resume (you must be speaking German!). + +=head1 SEE ALSO + +mysql documentation + +=cut diff --git a/sql/derror.cc b/sql/derror.cc index 697d363b86b..bda0690ae7d 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -51,6 +51,7 @@ static void read_texts(const char *file_name,const char ***point, uchar head[32],*pos; DBUG_ENTER("read_texts"); + *point=0; // If something goes wrong LINT_INIT(buff); funktpos=0; if ((file=my_open(fn_format(name,file_name,language,"",4), diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a4421bc139c..8854f6b46d2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -741,7 +741,7 @@ void clean_up(bool print_message) if (!opt_bootstrap) (void) my_delete(pidfile_name,MYF(0)); // This may not always exist #endif - if (print_message) + if (print_message && errmesg) sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname); x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */ @@ -3688,7 +3688,7 @@ static void get_options(int argc,char **argv) opt_specialflag|= SPECIAL_NO_HOST_CACHE; break; case (int) OPT_ENABLE_LOCK: - my_disable_locking=0; + my_disable_locking=myisam_single_user=0; break; case (int) OPT_USE_LOCKING: my_disable_locking=0; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 1103e5590d8..8ba293c82f9 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -274,6 +274,8 @@ multi_delete::initialize_tables(JOIN *join) /* We are going to delete from this table */ walk->table=tab->table; walk=walk->next; + if (tab == join->join_tab) + tab->table->no_keyread=1; } } } @@ -353,6 +355,10 @@ void multi_delete::send_error(uint errcode,const char *err) { /* First send error what ever it is ... */ ::send_error(&thd->net,errcode,err); + + /* reset used flags */ + delete_tables->table->no_keyread=0; + /* If nothing deleted return */ if (!deleted) return; @@ -451,6 +457,9 @@ bool multi_delete::send_eof() thd->proc_info="deleting from reference tables"; int error = do_deletes(false); + /* reset used flags */ + delete_tables->table->no_keyread=0; + thd->proc_info="end"; if (error && error != -1) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c2bb282a624..14bdd3d7d66 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2489,7 +2489,8 @@ make_join_readinfo(JOIN *join,uint options) table->file->index_init(tab->ref.key); tab->read_first_record= join_read_key; tab->read_record.read_record= join_no_more_records; - if (table->used_keys & ((key_map) 1 << tab->ref.key)) + if (table->used_keys & ((key_map) 1 << tab->ref.key) && + !table->no_keyread) { table->key_read=1; table->file->extra(HA_EXTRA_KEYREAD); @@ -2507,7 +2508,8 @@ make_join_readinfo(JOIN *join,uint options) table->file->index_init(tab->ref.key); tab->read_first_record= join_read_always_key; tab->read_record.read_record= join_read_next; - if (table->used_keys & ((key_map) 1 << tab->ref.key)) + if (table->used_keys & ((key_map) 1 << tab->ref.key) && + !table->no_keyread) { table->key_read=1; table->file->extra(HA_EXTRA_KEYREAD); @@ -2568,18 +2570,21 @@ make_join_readinfo(JOIN *join,uint options) statistic_increment(select_full_join_count, &LOCK_status); } } - if (tab->select && tab->select->quick && - table->used_keys & ((key_map) 1 << tab->select->quick->index)) + if (!table->no_keyread) { - table->key_read=1; - table->file->extra(HA_EXTRA_KEYREAD); - } - else if (table->used_keys && ! (tab->select && tab->select->quick)) - { // Only read index tree - tab->index=find_shortest_key(table, table->used_keys); - tab->table->file->index_init(tab->index); - tab->read_first_record= join_init_read_first_with_key; - tab->type=JT_NEXT; // Read with index_first / index_next + if (tab->select && tab->select->quick && + table->used_keys & ((key_map) 1 << tab->select->quick->index)) + { + table->key_read=1; + table->file->extra(HA_EXTRA_KEYREAD); + } + else if (table->used_keys && ! (tab->select && tab->select->quick)) + { // Only read index tree + tab->index=find_shortest_key(table, table->used_keys); + tab->table->file->index_init(tab->index); + tab->read_first_record= join_init_read_first_with_key; + tab->type=JT_NEXT; // Read with index_first / index_next + } } } break; @@ -4556,7 +4561,8 @@ join_init_read_first_with_key(JOIN_TAB *tab) { int error; TABLE *table=tab->table; - if (!table->key_read && (table->used_keys & ((key_map) 1 << tab->index))) + if (!table->key_read && (table->used_keys & ((key_map) 1 << tab->index)) && + !table->no_keyread) { table->key_read=1; table->file->extra(HA_EXTRA_KEYREAD); diff --git a/sql/table.h b/sql/table.h index 1eead0decb1..071c447e660 100644 --- a/sql/table.h +++ b/sql/table.h @@ -97,6 +97,7 @@ struct st_table { my_bool locked_by_name; my_bool crashed; my_bool is_view; + my_bool no_keyread; Field *next_number_field, /* Set if next_number is activated */ *found_next_number_field, /* Set on open */ *rowid_field; diff --git a/tools/mysqlmanager.c b/tools/mysqlmanager.c index 5b32cc9154e..4ec9c765e7c 100644 --- a/tools/mysqlmanager.c +++ b/tools/mysqlmanager.c @@ -39,8 +39,7 @@ #include #define MANAGER_VERSION "1.0" -#define MANAGER_GREETING "MySQL Server Management Daemon v." ## \ - MANAGER_VERSION +#define MANAGER_GREETING "MySQL Server Management Daemon v. 1.0" #define LOG_ERR 1 #define LOG_WARN 2 @@ -218,23 +217,23 @@ struct manager_exec int num_args; }; -#define HANDLE_DECL(com) static int handle_ ## com (struct manager_thd* thd,\ +#define HANDLE_DECL(com) static int com (struct manager_thd* thd,\ char* args_start,char* args_end) -#define HANDLE_NOARG_DECL(com) static int handle_ ## com \ +#define HANDLE_NOARG_DECL(com) static int com \ (struct manager_thd* thd, char* __attribute__((unused)) args_start,\ char* __attribute__((unused)) args_end) -HANDLE_NOARG_DECL(ping); -HANDLE_NOARG_DECL(quit); -HANDLE_NOARG_DECL(help); -HANDLE_NOARG_DECL(shutdown); -HANDLE_DECL(def_exec); -HANDLE_DECL(start_exec); -HANDLE_DECL(stop_exec); -HANDLE_DECL(set_exec_con); -HANDLE_NOARG_DECL(show_exec); +HANDLE_NOARG_DECL(handle_ping); +HANDLE_NOARG_DECL(handle_quit); +HANDLE_NOARG_DECL(handle_help); +HANDLE_NOARG_DECL(handle_shutdown); +HANDLE_DECL(handle_def_exec); +HANDLE_DECL(handle_start_exec); +HANDLE_DECL(handle_stop_exec); +HANDLE_DECL(handle_set_exec_con); +HANDLE_NOARG_DECL(handle_show_exec); struct manager_cmd commands[] = { @@ -375,20 +374,20 @@ static struct manager_cmd* lookup_cmd(char* s,int len) return 0; } -HANDLE_NOARG_DECL(ping) +HANDLE_NOARG_DECL(handle_ping) { client_msg(thd->vio,MSG_OK,"Server management daemon is alive"); return 0; } -HANDLE_NOARG_DECL(quit) +HANDLE_NOARG_DECL(handle_quit) { client_msg(thd->vio,MSG_OK,"Goodbye"); thd->finished=1; return 0; } -HANDLE_NOARG_DECL(help) +HANDLE_NOARG_DECL(handle_help) { struct manager_cmd* cmd = commands; Vio* vio = thd->vio; @@ -401,7 +400,7 @@ HANDLE_NOARG_DECL(help) return 0; } -HANDLE_NOARG_DECL(shutdown) +HANDLE_NOARG_DECL(handle_shutdown) { client_msg(thd->vio,MSG_OK,"Shutdown started, goodbye"); thd->finished=1; @@ -414,7 +413,7 @@ HANDLE_NOARG_DECL(shutdown) return 0; } -HANDLE_DECL(set_exec_con) +HANDLE_DECL(handle_set_exec_con) { int num_args; const char* error=0; @@ -461,7 +460,7 @@ err: return 1; } -HANDLE_DECL(start_exec) +HANDLE_DECL(handle_start_exec) { int num_args; struct manager_exec* e; @@ -509,7 +508,7 @@ err: return 1; } -HANDLE_DECL(stop_exec) +HANDLE_DECL(handle_stop_exec) { int num_args; struct timespec abstime; @@ -564,7 +563,7 @@ err: return 1; } -HANDLE_DECL(def_exec) +HANDLE_DECL(handle_def_exec) { struct manager_exec* e=0,*old_e; const char* error=0; @@ -597,7 +596,7 @@ err: return 1; } -HANDLE_NOARG_DECL(show_exec) +HANDLE_NOARG_DECL(handle_show_exec) { uint i; client_msg_pre(thd->vio,MSG_INFO,"Exec_def\tPid\tExit_status\tCon_info\ @@ -809,19 +808,19 @@ static void log_msg(const char* fmt, int msg_type, va_list args) pthread_mutex_unlock(&lock_log); } -#define LOG_MSG_FUNC(type,TYPE) inline static void log_ ## type \ +#define LOG_MSG_FUNC(type,TYPE) inline static void type \ (const char* fmt,...) { \ va_list args; \ va_start(args,fmt); \ - log_msg(fmt,LOG_ ## TYPE,args);\ + log_msg(fmt,TYPE,args);\ } -LOG_MSG_FUNC(err,ERR) -LOG_MSG_FUNC(warn,WARN) -LOG_MSG_FUNC(info,INFO) +LOG_MSG_FUNC(log_err,LOG_ERR) +LOG_MSG_FUNC(log_warn,LOG_WARN) +LOG_MSG_FUNC(log_info,LOG_INFO) #ifndef DBUG_OFF -LOG_MSG_FUNC(debug,DEBUG) +LOG_MSG_FUNC(log_debug,LOG_DEBUG) #else void log_debug(char* __attribute__((unused)) fmt,...) {} #endif