From d1f560ef7be0df8052b0b094453ab5e46a22c887 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Nov 2001 09:57:36 -0700 Subject: [PATCH 1/3] properly kill slave in all cases on systems that do not interrupt syscalls on a signal --- sql/sql_repl.cc | 11 ++++------- sql/sql_repl.h | 7 +++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 7d4a7847eb1..1940ff360c2 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -602,16 +602,13 @@ int stop_slave(THD* thd, bool net_report ) if (slave_running) { abort_slave = 1; - thr_alarm_kill(slave_real_id); -#ifdef SIGNAL_WITH_VIO_CLOSE - slave_thd->close_active_vio(); -#endif + KICK_SLAVE; // do not abort the slave in the middle of a query, so we do not set // thd->killed for the slave thread thd->proc_info = "waiting for slave to die"; while(slave_running) { - /* there is a small change that slave thread might miss the first + /* there is a small chance that slave thread might miss the first alarm. To protect againts it, resend the signal until it reacts */ @@ -630,7 +627,7 @@ int stop_slave(THD* thd, bool net_report ) #endif pthread_cond_timedwait(&COND_slave_stopped, &LOCK_slave, &abstime); if (slave_running) - thr_alarm_kill(slave_real_id); + KICK_SLAVE; } } else @@ -716,7 +713,7 @@ int change_master(THD* thd) if((slave_was_running = slave_running)) { abort_slave = 1; - thr_alarm_kill(slave_real_id); + KICK_SLAVE; thd->proc_info = "waiting for slave to die"; while(slave_running) pthread_cond_wait(&COND_slave_stopped, &LOCK_slave); // wait until done diff --git a/sql/sql_repl.h b/sql/sql_repl.h index c6a79ec4650..aa07d859aec 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -14,6 +14,13 @@ extern int max_binlog_dump_events; extern bool opt_sporadic_binlog_dump_fail; #endif +#ifdef SIGNAL_WITH_VIO_CLOSE +#define KICK_SLAVE { slave_thd->close_active_vio(); \ + thr_alarm_kill(slave_real_id); } +#else +#define KICK_SLAVE thr_alarm_kill(slave_real_id); +#endif + File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg); From 4615e50093d635f07f2940bb9fbe7e1c327b8ebb Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Nov 2001 02:16:38 +0200 Subject: [PATCH 2/3] Fix race condition in ANALYZE TABLE. Fixed bug where one got an empty set instead of a DEADLOCK error when using BDB tables. Docs/manual.texi: Cleanup configure.in: Version number change mysql-test/t/backup.test: drop used tables mysql-test/t/bdb-crash.test: cleanup mysys/thr_lock.c: cleanup sql/mysqld.cc: safety fix sql/records.cc: Fixed bug where one got an empty set instead of a DEADLOCK error when using BDB tables. sql/sql_table.cc: Fix race condition in ANALYZE TABLE. --- Docs/manual.texi | 16 ++++++++++- configure.in | 2 +- mysql-test/r/bdb-deadlock.result | 10 +++++++ mysql-test/t/backup.test | 1 + mysql-test/t/bdb-crash.test | 14 +++++----- mysql-test/t/bdb-deadlock.test | 48 ++++++++++++++++++++++++++++++++ mysys/thr_lock.c | 3 +- sql/mysqld.cc | 2 +- sql/records.cc | 44 +++++++++++++++++++++-------- sql/sql_table.cc | 5 +++- 10 files changed, 121 insertions(+), 24 deletions(-) create mode 100644 mysql-test/r/bdb-deadlock.result create mode 100644 mysql-test/t/bdb-deadlock.test diff --git a/Docs/manual.texi b/Docs/manual.texi index 07959fd2602..9eff296b7e6 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -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. @menu +* News-3.23.46:: * News-3.23.45:: Changes in release 3.23.45 * News-3.23.44:: Changes in release 3.23.44 * News-3.23.43:: Changes in release 3.23.43 @@ -46834,7 +46835,20 @@ not yet 100% confident in this code. * News-3.23.0:: Changes in release 3.23.0 @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 @itemize @bullet @item diff --git a/configure.in b/configure.in index bccc323b7bd..4149b0ab5c9 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # 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) PROTOCOL_VERSION=10 diff --git a/mysql-test/r/bdb-deadlock.result b/mysql-test/r/bdb-deadlock.result new file mode 100644 index 00000000000..89077d16980 --- /dev/null +++ b/mysql-test/r/bdb-deadlock.result @@ -0,0 +1,10 @@ +x +1 +id x +0 1 +id x +0 1 +id x +0 1 +id x +0 1 diff --git a/mysql-test/t/backup.test b/mysql-test/t/backup.test index 43ea6fd19ad..71343783d69 100644 --- a/mysql-test/t/backup.test +++ b/mysql-test/t/backup.test @@ -39,6 +39,7 @@ reap; unlock tables; connection con1; reap; +drop table t1; diff --git a/mysql-test/t/bdb-crash.test b/mysql-test/t/bdb-crash.test index 05ab7260d23..55e00ad2a5e 100644 --- a/mysql-test/t/bdb-crash.test +++ b/mysql-test/t/bdb-crash.test @@ -1,7 +1,7 @@ # test for bug reported by Mark Steele -drop table if exists tblChange; -CREATE TABLE tblCharge ( +drop table if exists t1; +CREATE TABLE t1 ( ChargeID int(10) unsigned DEFAULT '0' NOT NULL auto_increment, ServiceID int(10) unsigned DEFAULT '0' NOT NULL, ChargeDate date DEFAULT '0000-00-00' NOT NULL, @@ -19,16 +19,16 @@ DEFAULT 'New' NOT NULL, ) type=BDB; BEGIN; -INSERT INTO tblCharge +INSERT INTO t1 VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now'); COMMIT; BEGIN; -UPDATE tblCharge SET ChargeAuthorizationMessage = 'blablabla' WHERE +UPDATE t1 SET ChargeAuthorizationMessage = 'blablabla' WHERE ChargeID = 1; COMMIT; -INSERT INTO tblCharge +INSERT INTO t1 VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now'); -select * from tblCharge; -drop table tblCharge; +select * from t1; +drop table t1; diff --git a/mysql-test/t/bdb-deadlock.test b/mysql-test/t/bdb-deadlock.test new file mode 100644 index 00000000000..b32b50c715b --- /dev/null +++ b/mysql-test/t/bdb-deadlock.test @@ -0,0 +1,48 @@ +# 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; diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 10c803378df..aa50877072d 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -913,7 +913,8 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count) 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 */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d5aa54960e8..82fc5556bd8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -718,8 +718,8 @@ void clean_up(bool print_message) if (!opt_noacl) udf_free(); #endif - end_key_cache(); (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */ + end_key_cache(); #ifdef USE_RAID end_raid(); #endif diff --git a/sql/records.cc b/sql/records.cc index 0f49b3fa45e..d436f4f58fe 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -132,8 +132,13 @@ static int rr_quick(READ_RECORD *info) { if (tmp == HA_ERR_END_OF_FILE) tmp= -1; - else if (info->print_error) - info->file->print_error(tmp,MYF(0)); + else + { + if (info->print_error) + info->file->print_error(tmp,MYF(0)); + if (tmp < 0) // Fix negative BDB errno + tmp=1; + } } return tmp; } @@ -153,8 +158,13 @@ static int rr_sequential(READ_RECORD *info) { if (tmp == HA_ERR_END_OF_FILE) tmp= -1; - else if (info->print_error) - info->table->file->print_error(tmp,MYF(0)); + else + { + if (info->print_error) + info->table->file->print_error(tmp,MYF(0)); + if (tmp < 0) // Fix negative BDB errno + tmp=1; + } break; } } @@ -168,21 +178,27 @@ static int rr_from_tempfile(READ_RECORD *info) tryNext: if (my_b_read(info->io_cache,info->ref_pos,info->ref_length)) return -1; /* End of file */ - tmp=info->file->rnd_pos(info->record,info->ref_pos); - if (tmp) + if ((tmp=info->file->rnd_pos(info->record,info->ref_pos))) { if (tmp == HA_ERR_END_OF_FILE) tmp= -1; else if (tmp == HA_ERR_RECORD_DELETED) goto tryNext; - else if (info->print_error) - info->file->print_error(tmp,MYF(0)); + else + { + if (info->print_error) + info->file->print_error(tmp,MYF(0)); + if (tmp < 0) // Fix negative BDB errno + tmp=1; + } } return tmp; } /* rr_from_tempfile */ + static int rr_from_pointers(READ_RECORD *info) { + int tmp; byte *cache_pos; tryNext: if (info->cache_pos == info->cache_end) @@ -190,15 +206,19 @@ tryNext: cache_pos=info->cache_pos; info->cache_pos+=info->ref_length; - int tmp=info->file->rnd_pos(info->record,cache_pos); - if (tmp) + if ((tmp=info->file->rnd_pos(info->record,cache_pos))) { if (tmp == HA_ERR_END_OF_FILE) tmp= -1; else if (tmp == HA_ERR_RECORD_DELETED) goto tryNext; - else if (info->print_error) - info->file->print_error(tmp,MYF(0)); + else + { + if (info->print_error) + info->file->print_error(tmp,MYF(0)); + if (tmp < 0) // Fix negative BDB errno + tmp=1; + } } return tmp; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 725aed390be..f4735df5451 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -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 */ - if (open_for_modify && table->table->version) + if (lock_type == TL_WRITE && table->table->version) { 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); while (remove_table_from_cache(thd, table->table->table_cache_key, table->table->real_name) && @@ -976,6 +978,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, (void) pthread_cond_wait(&COND_refresh,&LOCK_open); dropping_tables--; } + thd->exit_cond(old_message); pthread_mutex_unlock(&LOCK_open); if (thd->killed) goto err; From 22e34307afbbd33b8100bf26f5a012a9f0fb7d7b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Nov 2001 03:24:13 +0200 Subject: [PATCH 3/3] A fix for ANALYZE TABLE --- sql/sql_table.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f4735df5451..aa54f325ebb 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -982,6 +982,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, pthread_mutex_unlock(&LOCK_open); if (thd->killed) goto err; + open_for_modify=0; } int result_code = (table->table->file->*operator_func)(thd, check_opt); @@ -1029,6 +1030,9 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, } if (fatal_error) table->table->version=0; // Force close of table + else if (open_for_modify) + remove_table_from_cache(thd, table->table->table_cache_key, + table->table->real_name); close_thread_tables(thd); if (my_net_write(&thd->net, (char*) packet->ptr(), packet->length()))