Commit 4de34841 authored by monty@donna.mysql.fi's avatar monty@donna.mysql.fi

Merge work:/my/mysql into donna.mysql.fi:/home/my/bk/mysql

parents c91715e3 32d403f0
This diff is collapsed.
...@@ -3,3 +3,8 @@ a tmsp ...@@ -3,3 +3,8 @@ a tmsp
5 19711006010203 5 19711006010203
6 19711006010203 6 19711006010203
8 19711006010203 8 19711006010203
a b
1 b
2 c
3 d
4 e
...@@ -15,3 +15,17 @@ insert into t1 set a = 8,tmsp=19711006010203; ...@@ -15,3 +15,17 @@ insert into t1 set a = 8,tmsp=19711006010203;
select * from t1 where tmsp=0; select * from t1 where tmsp=0;
select * from t1 where tmsp=19711006010203; select * from t1 where tmsp=19711006010203;
drop table t1; drop table t1;
#
# Test bug when inserting NULL into an auto_increment field with
# INSERT DELAYED
#
create table t1 (a int not null auto_increment primary key, b char(10));
insert delayed into t1 values (1,"b");
insert delayed into t1 values (null,"c");
insert delayed into t1 values (3,"d"),(null,"e");
--error 1136
insert delayed into t1 values (3,"this will give an","error");
select * from t1;
drop table t1;
#!@PERL@ #!@PERL@
# mysqldumpslow - parse and summarize the MySQL slow query log # mysqldumpslow - parse and summarize the MySQL slow query log
# Original version by Tim Bunce, sometime in 2000.
# Further changes by Tim Bunce, 8th March 2001.
use strict; use strict;
use Getopt::Long; use Getopt::Long;
...@@ -8,69 +11,128 @@ use Getopt::Long; ...@@ -8,69 +11,128 @@ use Getopt::Long;
# at, al, and ar are the corresponding averages # at, al, and ar are the corresponding averages
my %opt = ( my %opt = (
s => 'at', s => 'at',
h => '*', h => '*',
); );
GetOptions(\%opt, GetOptions(\%opt,
'v+', # verbose 'v+', # verbose
'd+', # debug 'd+', # debug
's=s', # what to sort by (t, at, l, al, r, ar etc) 's=s', # what to sort by (t, at, l, al, r, ar etc)
'a!', # don't abstract all numbers to N and strings to 'S' 'r!', # reverse the sort order (largest last instead of first)
'g=s', # grep: only consider stmts that include this string 't=i', # just show the top n queries
'h=s', # hostname of db server (can be wildcard) 'a!', # don't abstract all numbers to N and strings to 'S'
'n=i', # abstract numbers with at least n digits within names
'g=s', # grep: only consider stmts that include this string
'h=s', # hostname of db server for *-slow.log filename (can be wildcard)
'i=s', # name of server instance (if using mysql.server startup script)
'l!', # don't subtract lock time from total time
) or die "Bad option"; ) or die "Bad option";
my %stmt;
my $datadir = "/var/lib/mysql"; # XXX should fetch dynamically
@ARGV = <$datadir/$opt{h}-slow.log>;
$/ = "\n#"; # read entire statements using paragraph mode
while (<>) {
print "[$_]\n" if $opt{v};
s/^#// unless %stmt;
s/\s*Time: (\d+) Lock_time: (\d+) Rows_sent: (\d+).*\n//;
my ($t, $l, $r) = ($1, $2, $3);
s/^use \w+;\n//; # not consistently added unless (@ARGV) {
s/^SET timestamp=\d+;\n//; my $defaults = `my_print_defaults mysqld`;
my $basedir = ($defaults =~ m/--basedir=(.*)/)[0]
s/^[ ]*\n//mg; # delete blank lines or die "Can't determine basedir from 'my_print_defaults mysqld' output: $defaults";
s/^[ ]*/ /mg; # normalize leading whitespace warn "basedir=$basedir\n" if $opt{v};
s/\s*;\s*(#\s*)?$//; # remove traing semicolon(+newline-hash)
my $datadir = ($defaults =~ m/--datadir=(.*)/)[0];
next if $opt{g} and !m/$opt{g}/i; if (!$datadir or $opt{i}) {
# determine the datadir from the instances section of /etc/my.cnf, if any
unless ($opt{a}) { my $instances = `my_print_defaults instances`;
s/\b\d+\b/N/g; die "Can't determine datadir from 'my_print_defaults mysqld' output: $defaults"
s/\b0x[0-9A-Fa-f]+\b/N/g; unless $instances;
s/'.*?'/'S'/g; my @instances = ($instances =~ m/^--(\w+)-/mg);
s/".*?"/"S"/g; die "No -i 'instance_name' specified to select among known instances: @instances.\n"
} unless $opt{i};
die "Instance '$opt{i}' is unknown (known instances: @instances)\n"
unless grep { $_ eq $opt{i} } @instances;
$datadir = ($instances =~ m/--$opt{i}-datadir=(.*)/)[0]
or die "Can't determine --$opt{i}-datadir from 'my_print_defaults instances' output: $instances";
warn "datadir=$datadir\n" if $opt{v};
}
@ARGV = <$datadir/$opt{h}-slow.log>;
die "Can't find '$datadir/$opt{h}-slow.log'\n" unless @ARGV;
}
$stmt{$_}->{c} += 1; warn "\nReading mysql slow query log from @ARGV\n";
$stmt{$_}->{t} += $t;
$stmt{$_}->{l} += $l;
$stmt{$_}->{r} += $r;
warn "[$_]" if $opt{d}; my @pending;
my %stmt;
$/ = ";\n#"; # read entire statements using paragraph mode
while ( defined($_ = shift @pending) or defined($_ = <>) ) {
warn "[[$_]]\n" if $opt{d}; # show raw paragraph being read
my @chunks = split /^\/.*Version.*started with[\000-\377]*?Time.*Id.*Command.*Argument.*\n/m;
if (@chunks > 1) {
unshift @pending, map { length($_) ? $_ : () } @chunks;
warn "<<".join(">>\n<<",@chunks).">>" if $opt{d};
next;
}
s/^#? Time: \d{6}\s+\d+:\d+:\d+.*\n//;
my ($user,$host) = s/^#? User\@Host:\s+(\S+)\s+\@\s+(\S+).*\n// ? ($1,$2) : ('','');
s/^# Time: (\d+) Lock_time: (\d+) Rows_sent: (\d+).*\n//;
my ($t, $l, $r) = ($1, $2, $3);
$t -= $l unless $opt{l};
# remove fluff that mysqld writes to log when it (re)starts:
s!^/.*Version.*started with:.*\n!!mg;
s!^Tcp port: \d+ Unix socket: \S+\n!!mg;
s!^Time.*Id.*Command.*Argument.*\n!!mg;
s/^use \w+;\n//; # not consistently added
s/^SET timestamp=\d+;\n//;
s/^[ ]*\n//mg; # delete blank lines
s/^[ ]*/ /mg; # normalize leading whitespace
s/\s*;\s*(#\s*)?$//; # remove trailing semicolon(+newline-hash)
next if $opt{g} and !m/$opt{g}/io;
unless ($opt{a}) {
s/\b\d+\b/N/g;
s/\b0x[0-9A-Fa-f]+\b/N/g;
s/'.*?'/'S'/g;
s/".*?"/"S"/g;
# -n=8: turn log_20001231 into log_NNNNNNNN
s/([a-z_]+)(\d{$opt{n},})/$1.('N' x length($2))/ieg if $opt{n};
# abbreviate massive "in (...)" statements and similar
s!(([NS],){100,})!sprintf("$2,{repeated %d times}",length($1)/2)!eg;
}
my $s = $stmt{$_} ||= { users=>{}, hosts=>{} };
$s->{c} += 1;
$s->{t} += $t;
$s->{l} += $l;
$s->{r} += $r;
$s->{users}->{$user}++ if $user;
$s->{hosts}->{$host}++ if $host;
warn "{{$_}}\n\n" if $opt{d}; # show processed statement string
} }
foreach (keys %stmt) { foreach (keys %stmt) {
my $v = $stmt{$_} || die; my $v = $stmt{$_} || die;
my ($c, $t, $l, $r) = @{ $v }{qw(c t l r)}; my ($c, $t, $l, $r) = @{ $v }{qw(c t l r)};
$v->{at} = $t / $c; $v->{at} = $t / $c;
$v->{al} = $l / $c; $v->{al} = $l / $c;
$v->{ar} = $r / $c; $v->{ar} = $r / $c;
} }
my @sorted = sort { $stmt{$a}->{$opt{s}} <=> $stmt{$b}->{$opt{s}} } keys %stmt; my @sorted = sort { $stmt{$b}->{$opt{s}} <=> $stmt{$a}->{$opt{s}} } keys %stmt;
@sorted = @sorted[0 .. $opt{t}-1] if $opt{t};
@sorted = reverse @sorted if $opt{r};
foreach (@sorted) { foreach (@sorted) {
my $v = $stmt{$_} || die; my $v = $stmt{$_} || die;
my ($c, $t,$at, $l,$al, $r,$ar) = @{ $v }{qw(c t at l al r ar)}; my ($c, $t,$at, $l,$al, $r,$ar) = @{ $v }{qw(c t at l al r ar)};
printf "Count: %d Time: %.2f (%d) Lock_time: %.2f (%d) Rows_sent: %.1f (%d) \n%s\n\n", my @users = keys %{$v->{users}};
$c, $at,$t, $al,$l, $ar,$r, $_; my $user = (@users==1) ? $users[0] : sprintf "%dusers",scalar @users;
my @hosts = keys %{$v->{hosts}};
my $host = (@hosts==1) ? $hosts[0] : sprintf "%dhosts",scalar @hosts;
printf "Count: %d Time=%.2fs (%ds) Lock=%.2fs (%ds) Rows=%.1f (%d), $user\@$host\n%s\n\n",
$c, $at,$t, $al,$l, $ar,$r, $_;
} }
...@@ -133,7 +133,8 @@ set_field_to_null(Field *field) ...@@ -133,7 +133,8 @@ set_field_to_null(Field *field)
return 0; return 0;
} }
if (!current_thd->no_errors) if (!current_thd->no_errors)
my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0),field->field_name); my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0),
field->field_name);
return 1; return 1;
} }
return 0; return 0;
......
...@@ -247,9 +247,12 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -247,9 +247,12 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
} }
if (lock_type == TL_WRITE_DELAYED) if (lock_type == TL_WRITE_DELAYED)
{ {
id=0; // No auto_increment id if (!error)
info.copied=values_list.elements; {
end_delayed_insert(thd); id=0; // No auto_increment id
info.copied=values_list.elements;
end_delayed_insert(thd);
}
} }
else else
{ {
...@@ -486,7 +489,7 @@ public: ...@@ -486,7 +489,7 @@ public:
table(0),tables_in_use(0),stacked_inserts(0), status(0), dead(0), table(0),tables_in_use(0),stacked_inserts(0), status(0), dead(0),
group_count(0) group_count(0)
{ {
thd.user=thd.host=(char*) ""; thd.user=0; thd.host=(char*) localhost;
thd.current_tablenr=0; thd.current_tablenr=0;
thd.version=refresh_version; thd.version=refresh_version;
thd.command=COM_DELAYED_INSERT; thd.command=COM_DELAYED_INSERT;
...@@ -676,7 +679,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) ...@@ -676,7 +679,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
TABLE *delayed_insert::get_local_table(THD* client_thd) TABLE *delayed_insert::get_local_table(THD* client_thd)
{ {
my_ptrdiff_t adjust_ptrs; my_ptrdiff_t adjust_ptrs;
Field **field,**org_field; Field **field,**org_field, *found_next_number_field;
TABLE *copy; TABLE *copy;
/* First request insert thread to get a lock */ /* First request insert thread to get a lock */
...@@ -719,11 +722,14 @@ TABLE *delayed_insert::get_local_table(THD* client_thd) ...@@ -719,11 +722,14 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
adjust_ptrs=PTR_BYTE_DIFF(copy->record[0],table->record[0]); adjust_ptrs=PTR_BYTE_DIFF(copy->record[0],table->record[0]);
found_next_number_field=table->found_next_number_field;
for (org_field=table->field ; *org_field ; org_field++,field++) for (org_field=table->field ; *org_field ; org_field++,field++)
{ {
if (!(*field= (*org_field)->new_field(copy))) if (!(*field= (*org_field)->new_field(copy)))
return 0; return 0;
(*field)->move_field(adjust_ptrs); // Point at copy->record[0] (*field)->move_field(adjust_ptrs); // Point at copy->record[0]
if (*org_field == found_next_number_field)
(*field)->table->found_next_number_field= *field;
} }
*field=0; *field=0;
...@@ -806,14 +812,17 @@ static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, ...@@ -806,14 +812,17 @@ static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic,
static void end_delayed_insert(THD *thd) static void end_delayed_insert(THD *thd)
{ {
DBUG_ENTER("end_delayed_insert");
delayed_insert *di=thd->di; delayed_insert *di=thd->di;
pthread_mutex_lock(&di->mutex); pthread_mutex_lock(&di->mutex);
DBUG_PRINT("info",("tables in use: %d",di->tables_in_use));
if (!--di->tables_in_use || di->thd.killed) if (!--di->tables_in_use || di->thd.killed)
{ // Unlock table { // Unlock table
di->status=1; di->status=1;
pthread_cond_signal(&di->cond); pthread_cond_signal(&di->cond);
} }
pthread_mutex_unlock(&di->mutex); pthread_mutex_unlock(&di->mutex);
DBUG_VOID_RETURN;
} }
...@@ -951,6 +960,7 @@ static pthread_handler_decl(handle_delayed_insert,arg) ...@@ -951,6 +960,7 @@ static pthread_handler_decl(handle_delayed_insert,arg)
pthread_mutex_unlock(&di->thd.mysys_var->mutex); pthread_mutex_unlock(&di->thd.mysys_var->mutex);
di->thd.proc_info=0; di->thd.proc_info=0;
DBUG_PRINT("info",("Waiting for someone to insert rows"));
for ( ; ;) for ( ; ;)
{ {
int error; int error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment