Commit 57381179 authored by monty@hundin.mysql.fi's avatar monty@hundin.mysql.fi

Fix race condition in ANALYZE TABLE.

Fixed bug where one got an empty set instead of a DEADLOCK error when using BDB tables.
parent a2a838f8
...@@ -46785,6 +46785,7 @@ users use this code as the rest of the code and because of this we are ...@@ -46785,6 +46785,7 @@ users use this code as the rest of the code and because of this we are
not yet 100% confident in this code. not yet 100% confident in this code.
@menu @menu
* News-3.23.46::
* News-3.23.45:: Changes in release 3.23.45 * News-3.23.45:: Changes in release 3.23.45
* News-3.23.44:: Changes in release 3.23.44 * News-3.23.44:: Changes in release 3.23.44
* News-3.23.43:: Changes in release 3.23.43 * News-3.23.43:: Changes in release 3.23.43
...@@ -46834,7 +46835,20 @@ not yet 100% confident in this code. ...@@ -46834,7 +46835,20 @@ not yet 100% confident in this code.
* News-3.23.0:: Changes in release 3.23.0 * News-3.23.0:: Changes in release 3.23.0
@end menu @end menu
@node News-3.23.45, News-3.23.44, News-3.23.x, News-3.23.x @node News-3.23.46, News-3.23.45, News-3.23.x, News-3.23.x
@appendixsubsec Changes in release 3.23.46
@itemize @bullet
@item
Fixed bug where one got an empty set instead of a DEADLOCK error when using
BDB tables.
@item
One can now kill @code{ANALYZE},@code{REPAIR} and @code{OPTIMIZE TABLE} when
the thread is waiting to get a lock on the table.
@item
Fixed race condition in @code{ANALYZE TABLE}.
@end itemize
@node News-3.23.45, News-3.23.44, News-3.23.46, News-3.23.x
@appendixsubsec Changes in release 3.23.45 @appendixsubsec Changes in release 3.23.45
@itemize @bullet @itemize @bullet
@item @item
...@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. ...@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(sql/mysqld.cc) AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line! # The Docs Makefile.am parses this line!
AM_INIT_AUTOMAKE(mysql, 3.23.45) AM_INIT_AUTOMAKE(mysql, 3.23.46)
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10 PROTOCOL_VERSION=10
......
x
1
id x
0 1
id x
0 1
id x
0 1
id x
0 1
...@@ -39,6 +39,7 @@ reap; ...@@ -39,6 +39,7 @@ reap;
unlock tables; unlock tables;
connection con1; connection con1;
reap; reap;
drop table t1;
......
# test for bug reported by Mark Steele # test for bug reported by Mark Steele
drop table if exists tblChange; drop table if exists t1;
CREATE TABLE tblCharge ( CREATE TABLE t1 (
ChargeID int(10) unsigned DEFAULT '0' NOT NULL auto_increment, ChargeID int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
ServiceID int(10) unsigned DEFAULT '0' NOT NULL, ServiceID int(10) unsigned DEFAULT '0' NOT NULL,
ChargeDate date DEFAULT '0000-00-00' NOT NULL, ChargeDate date DEFAULT '0000-00-00' NOT NULL,
...@@ -19,16 +19,16 @@ DEFAULT 'New' NOT NULL, ...@@ -19,16 +19,16 @@ DEFAULT 'New' NOT NULL,
) type=BDB; ) type=BDB;
BEGIN; BEGIN;
INSERT INTO tblCharge INSERT INTO t1
VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now'); VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now');
COMMIT; COMMIT;
BEGIN; BEGIN;
UPDATE tblCharge SET ChargeAuthorizationMessage = 'blablabla' WHERE UPDATE t1 SET ChargeAuthorizationMessage = 'blablabla' WHERE
ChargeID = 1; ChargeID = 1;
COMMIT; COMMIT;
INSERT INTO tblCharge INSERT INTO t1
VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now'); VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now');
select * from tblCharge; select * from t1;
drop table tblCharge; drop table t1;
# This test doesn't work with the embedded version as this code
# assumes that one query is running while we are doing queries on
# a second connection.
# This would work if mysqltest run would be threaded and handle each
# connection in a separate thread.
#
#-- source include/not_embedded.inc
-- source include/have_bdb.inc
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
drop table if exists t1,t2;
connection con1;
create table t1 (id integer, x integer) type=BDB;
create table t2 (id integer, x integer) type=BDB;
insert into t1 values(0, 0);
insert into t2 values(0, 0);
set autocommit=0;
update t1 set x = 1 where id = 0;
connection con2;
set autocommit=0;
update t2 set x = 1 where id = 0;
# The following query should hang because con1 is locking the page
--send
select x from t1 where id = 0;
connection con1;
# This should generate a deadlock as we are trying to access a locked row
--error 1213
select x from t2 where id = 0;
commit;
connection con2;
reap;
commit;
select * from t1;
select * from t2;
commit;
connection con1;
select * from t1;
select * from t2;
commit;
drop table t1,t2;
...@@ -913,7 +913,8 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count) ...@@ -913,7 +913,8 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/* Abort all threads waiting for a lock. The lock will be upgraded to a /*
Abort all threads waiting for a lock. The lock will be upgraded to
TL_WRITE_ONLY to abort any new accesses to the lock TL_WRITE_ONLY to abort any new accesses to the lock
*/ */
......
...@@ -718,8 +718,8 @@ void clean_up(bool print_message) ...@@ -718,8 +718,8 @@ void clean_up(bool print_message)
if (!opt_noacl) if (!opt_noacl)
udf_free(); udf_free();
#endif #endif
end_key_cache();
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */ (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
end_key_cache();
#ifdef USE_RAID #ifdef USE_RAID
end_raid(); end_raid();
#endif #endif
......
...@@ -132,8 +132,13 @@ static int rr_quick(READ_RECORD *info) ...@@ -132,8 +132,13 @@ static int rr_quick(READ_RECORD *info)
{ {
if (tmp == HA_ERR_END_OF_FILE) if (tmp == HA_ERR_END_OF_FILE)
tmp= -1; tmp= -1;
else if (info->print_error) else
info->file->print_error(tmp,MYF(0)); {
if (info->print_error)
info->file->print_error(tmp,MYF(0));
if (tmp < 0) // Fix negative BDB errno
tmp=1;
}
} }
return tmp; return tmp;
} }
...@@ -153,8 +158,13 @@ static int rr_sequential(READ_RECORD *info) ...@@ -153,8 +158,13 @@ static int rr_sequential(READ_RECORD *info)
{ {
if (tmp == HA_ERR_END_OF_FILE) if (tmp == HA_ERR_END_OF_FILE)
tmp= -1; tmp= -1;
else if (info->print_error) else
info->table->file->print_error(tmp,MYF(0)); {
if (info->print_error)
info->table->file->print_error(tmp,MYF(0));
if (tmp < 0) // Fix negative BDB errno
tmp=1;
}
break; break;
} }
} }
...@@ -168,21 +178,27 @@ static int rr_from_tempfile(READ_RECORD *info) ...@@ -168,21 +178,27 @@ static int rr_from_tempfile(READ_RECORD *info)
tryNext: tryNext:
if (my_b_read(info->io_cache,info->ref_pos,info->ref_length)) if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
return -1; /* End of file */ return -1; /* End of file */
tmp=info->file->rnd_pos(info->record,info->ref_pos); if ((tmp=info->file->rnd_pos(info->record,info->ref_pos)))
if (tmp)
{ {
if (tmp == HA_ERR_END_OF_FILE) if (tmp == HA_ERR_END_OF_FILE)
tmp= -1; tmp= -1;
else if (tmp == HA_ERR_RECORD_DELETED) else if (tmp == HA_ERR_RECORD_DELETED)
goto tryNext; goto tryNext;
else if (info->print_error) else
info->file->print_error(tmp,MYF(0)); {
if (info->print_error)
info->file->print_error(tmp,MYF(0));
if (tmp < 0) // Fix negative BDB errno
tmp=1;
}
} }
return tmp; return tmp;
} /* rr_from_tempfile */ } /* rr_from_tempfile */
static int rr_from_pointers(READ_RECORD *info) static int rr_from_pointers(READ_RECORD *info)
{ {
int tmp;
byte *cache_pos; byte *cache_pos;
tryNext: tryNext:
if (info->cache_pos == info->cache_end) if (info->cache_pos == info->cache_end)
...@@ -190,15 +206,19 @@ tryNext: ...@@ -190,15 +206,19 @@ tryNext:
cache_pos=info->cache_pos; cache_pos=info->cache_pos;
info->cache_pos+=info->ref_length; info->cache_pos+=info->ref_length;
int tmp=info->file->rnd_pos(info->record,cache_pos); if ((tmp=info->file->rnd_pos(info->record,cache_pos)))
if (tmp)
{ {
if (tmp == HA_ERR_END_OF_FILE) if (tmp == HA_ERR_END_OF_FILE)
tmp= -1; tmp= -1;
else if (tmp == HA_ERR_RECORD_DELETED) else if (tmp == HA_ERR_RECORD_DELETED)
goto tryNext; goto tryNext;
else if (info->print_error) else
info->file->print_error(tmp,MYF(0)); {
if (info->print_error)
info->file->print_error(tmp,MYF(0));
if (tmp < 0) // Fix negative BDB errno
tmp=1;
}
} }
return tmp; return tmp;
} }
......
...@@ -964,9 +964,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -964,9 +964,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
} }
/* Close all instances of the table to allow repair to rename files */ /* Close all instances of the table to allow repair to rename files */
if (open_for_modify && table->table->version) if (lock_type == TL_WRITE && table->table->version)
{ {
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
"Waiting to get writelock");
mysql_lock_abort(thd,table->table); mysql_lock_abort(thd,table->table);
while (remove_table_from_cache(thd, table->table->table_cache_key, while (remove_table_from_cache(thd, table->table->table_cache_key,
table->table->real_name) && table->table->real_name) &&
...@@ -976,6 +978,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -976,6 +978,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
(void) pthread_cond_wait(&COND_refresh,&LOCK_open); (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
dropping_tables--; dropping_tables--;
} }
thd->exit_cond(old_message);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
if (thd->killed) if (thd->killed)
goto err; goto err;
......
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