Commit 3446199d authored by unknown's avatar unknown

Fixed bug in LOCK TABLE + DROP TABLE when other thread was waiting for a table...

Fixed bug in LOCK TABLE + DROP TABLE when other thread was waiting for a table that was locked bug not droped


client/mysqltest.c:
  Fixed bug that comments did a ping
include/thr_lock.h:
  Added function to abort a lock for a specific thread
mysql-test/mysql-test-run.sh:
  Fixed where mysqltest traces are put
mysql-test/r/lock_multi.result:
  Test for LOCK TABLE + DROP TABLE bug
mysql-test/t/lock_multi.test:
  Test for LOCK TABLE + DROP TABLE bug
mysys/thr_lock.c:
  Added function to abort a lock for a specific thread
sql/handler.cc:
  Indentation cleanup
sql/lock.cc:
  Added function to abort a lock for a specific thread
sql/mysql_priv.h:
  Added function to abort a lock for a specific thread
sql/mysqld.cc:
  Use automatic recover even with --safe
parent 4c0f2f45
......@@ -2484,6 +2484,7 @@ int main(int argc, char** argv)
}
case Q_COMMENT: /* Ignore row */
case Q_COMMENT_WITH_COMMAND:
break;
case Q_PING:
(void) mysql_ping(&cur_con->mysql);
break;
......
......@@ -107,6 +107,7 @@ void thr_unlock(THR_LOCK_DATA *data);
int thr_multi_lock(THR_LOCK_DATA **data,uint count);
void thr_multi_unlock(THR_LOCK_DATA **data,uint count);
void thr_abort_locks(THR_LOCK *lock);
void thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread);
void thr_print_locks(void); /* For debugging */
my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data);
my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data);
......
......@@ -349,7 +349,8 @@ while test $# -gt 0; do
--debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/master.trace"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT \
--debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/slave.trace"
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT --debug"
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT \
--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqltest.trace"
;;
--fast)
FAST_START=1
......
drop table if exists t1;
drop table if exists t1,t2;
create table t1(n int);
insert into t1 values (1);
lock tables t1 write;
......@@ -17,3 +17,10 @@ unlock tables;
n
1
drop table t1;
create table t1 (a int);
create table t2 (a int);
lock table t1 write, t2 write;
insert t1 select * from t2;
drop table t2;
Table 'test.t2' doesn't exist
drop table t1;
......@@ -6,8 +6,9 @@
#
-- source include/not_embedded.inc
drop table if exists t1;
#test to see if select will get the lock ahead of low priority update
drop table if exists t1,t2;
# test to see if select will get the lock ahead of low priority update
connect (locker,localhost,root,,);
connect (reader,localhost,root,,);
......@@ -48,3 +49,22 @@ reap;
connection reader;
reap;
drop table t1;
#
# Test problem when using locks on many tables and droping a table that
# is to-be-locked by another thread
#
connection locker;
create table t1 (a int);
create table t2 (a int);
lock table t1 write, t2 write;
connection reader;
send insert t1 select * from t2;
connection locker;
drop table t2;
connection reader;
--error 1146
reap;
connection locker;
drop table t1;
......@@ -945,6 +945,54 @@ void thr_abort_locks(THR_LOCK *lock)
}
/*
Abort all locks for specific table/thread combination
This is used to abort all locks for a specific thread
*/
void thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread)
{
THR_LOCK_DATA *data;
DBUG_ENTER("thr_abort_locks_for_thread");
pthread_mutex_lock(&lock->mutex);
for (data= lock->read_wait.data; data ; data= data->next)
{
if (pthread_equal(thread, data->thread))
{
DBUG_PRINT("info",("Aborting read-wait lock"));
data->type= TL_UNLOCK; /* Mark killed */
pthread_cond_signal(data->cond);
data->cond= 0; /* Removed from list */
if (((*data->prev)= data->next))
data->next->prev= data->prev;
else
lock->read_wait.last= data->prev;
}
}
for (data= lock->write_wait.data; data ; data= data->next)
{
if (pthread_equal(thread, data->thread))
{
DBUG_PRINT("info",("Aborting write-wait lock"));
data->type= TL_UNLOCK;
pthread_cond_signal(data->cond);
data->cond= 0;
if (((*data->prev)= data->next))
data->next->prev= data->prev;
else
lock->write_wait.last= data->prev;
}
}
pthread_mutex_unlock(&lock->mutex);
DBUG_VOID_RETURN;
}
/* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */
my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
......
......@@ -473,7 +473,8 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
int error;
DBUG_ENTER("handler::open");
DBUG_PRINT("enter",("name: %s db_type: %d db_stat: %d mode: %d lock_test: %d",
name, table->db_type, table->db_stat, mode, test_if_locked));
name, table->db_type, table->db_stat, mode,
test_if_locked));
if ((error=open(name,mode,test_if_locked)))
{
......
......@@ -313,6 +313,25 @@ void mysql_lock_abort(THD *thd, TABLE *table)
}
/* Abort one thread / table combination */
void mysql_lock_abort_for_thread(THD *thd, TABLE *table)
{
MYSQL_LOCK *locked;
TABLE *write_lock_used;
DBUG_ENTER("mysql_lock_abort_for_thread");
if ((locked = get_lock_data(thd,&table,1,1,&write_lock_used)))
{
for (uint i=0; i < locked->lock_count; i++)
thr_abort_locks_for_thread(locked->locks[i]->lock,
table->in_use->real_id);
my_free((gptr) locked,MYF(0));
}
DBUG_VOID_RETURN;
}
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
{
MYSQL_LOCK *sql_lock;
......
......@@ -711,6 +711,7 @@ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
void mysql_lock_abort(THD *thd, TABLE *table);
void mysql_lock_abort_for_thread(THD *thd, TABLE *table);
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
bool lock_global_read_lock(THD *thd);
void unlock_global_read_lock(THD *thd);
......
......@@ -4416,8 +4416,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case (int) OPT_SAFE:
opt_specialflag|= SPECIAL_SAFE_MODE;
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
myisam_recover_options= HA_RECOVER_NONE; // To be changed
ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
myisam_recover_options= HA_RECOVER_DEFAULT;
ha_open_options&= ~(HA_OPEN_DELAY_KEY_WRITE);
break;
case (int) OPT_SKIP_PRIOR:
opt_specialflag|= SPECIAL_NO_PRIOR;
......
......@@ -1244,25 +1244,44 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name)
}
/* lock table to force abort of any threads trying to use table */
/*
If we have the table open, which only happens when a LOCK TABLE has been
done on the table, change the lock type to a lock that will abort all
other threads trying to get the lock.
*/
void abort_locked_tables(THD *thd,const char *db, const char *table_name)
{
TABLE *table;
for (table=thd->open_tables; table ; table=table->next)
for (table= thd->open_tables; table ; table= table->next)
{
if (!strcmp(table->real_name,table_name) &&
!strcmp(table->table_cache_key,db))
{
mysql_lock_abort(thd,table);
break;
}
}
}
/****************************************************************************
** open_unireg_entry
** Purpose : Load a table definition from file and open unireg table
** Args : entry with DB and table given
** Returns : 0 if ok
** Note that the extra argument for open is taken from thd->open_options
/*
Load a table definition from file and open unireg table
SYNOPSIS
open_unireg_entry()
thd Thread handle
entry Store open table definition here
db Database name
name Table name
alias Alias name
NOTES
Extra argument for open is taken from thd->open_options
RETURN
0 ok
# Error
*/
static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
......@@ -2277,6 +2296,17 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
}
pthread_mutex_unlock(&in_use->mysys_var->mutex);
}
/*
Now we must abort all tables locks used by this thread
as the thread may be waiting to get a lock for another table
*/
for (TABLE *thd_table= in_use->open_tables;
thd_table ;
thd_table= thd_table->next)
{
if (thd_table->db_stat) // If table is open
mysql_lock_abort_for_thread(thd, thd_table);
}
}
else
result= result || return_if_owned_by_thd;
......
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