Commit 98c4476b authored by Konstantin Osipov's avatar Konstantin Osipov

Backport of:

------------------------------------------------------------
revno: 2476.1116.1
committer: davi@mysql.com/endora.local
timestamp: Fri 2007-12-14 10:10:19 -0200
message:
DROP TABLE under LOCK TABLES simultaneous to a FLUSH TABLES
WITH READ LOCK (global read lock) can lead to a deadlock.

The solution is to not wait for the global read lock if the
thread is holding any locked tables.

Related to bugs 23713 and 32395. This issues is being fixed
only on 6.0 because it depends on the fix for bug 25858 --
which was fixed only on 6.0.
parent 1b34d593
...@@ -210,3 +210,12 @@ select @tlwa < @tlwb; ...@@ -210,3 +210,12 @@ select @tlwa < @tlwb;
@tlwa < @tlwb @tlwa < @tlwb
1 1
End of 5.1 tests End of 5.1 tests
drop table if exists t1;
create table t1 (i int);
connection: default
lock tables t1 write;
connection: flush
flush tables with read lock;;
connection: default
flush tables;
drop table t1;
...@@ -636,6 +636,41 @@ select @tlwa < @tlwb; ...@@ -636,6 +636,41 @@ select @tlwa < @tlwb;
--echo End of 5.1 tests --echo End of 5.1 tests
#
# Test that DROP TABLES does not wait for a impending FLUSH TABLES
# WITH READ LOCK
#
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (i int);
connect (flush,localhost,root,,test,,);
connection default;
--echo connection: default
lock tables t1 write;
connection flush;
--echo connection: flush
--send flush tables with read lock;
connection default;
--echo connection: default
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Flushing tables";
--source include/wait_condition.inc
flush tables;
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Flushing tables";
--source include/wait_condition.inc
drop table t1;
let $wait_condition=
select count(*) = 0 from information_schema.processlist
where state = "Flushing tables";
--source include/wait_condition.inc
connection flush;
--reap
connection default;
disconnect flush;
# Wait till all disconnects are completed # Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc --source include/wait_until_count_sessions.inc
...@@ -1766,7 +1766,8 @@ void write_bin_log(THD *thd, bool clear_error, ...@@ -1766,7 +1766,8 @@ void write_bin_log(THD *thd, bool clear_error,
If a table is in use, we will wait for all users to free the table If a table is in use, we will wait for all users to free the table
before dropping it before dropping it
Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set. Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
not if under LOCK TABLES.
RETURN RETURN
FALSE OK. In this case ok packet is sent to user FALSE OK. In this case ok packet is sent to user
...@@ -1777,7 +1778,7 @@ void write_bin_log(THD *thd, bool clear_error, ...@@ -1777,7 +1778,7 @@ void write_bin_log(THD *thd, bool clear_error,
bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
my_bool drop_temporary) my_bool drop_temporary)
{ {
bool error= FALSE, need_start_waiters= FALSE; bool error= FALSE, need_start_waiting= FALSE;
Drop_table_error_handler err_handler(thd->get_internal_handler()); Drop_table_error_handler err_handler(thd->get_internal_handler());
DBUG_ENTER("mysql_rm_table"); DBUG_ENTER("mysql_rm_table");
...@@ -1785,14 +1786,10 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, ...@@ -1785,14 +1786,10 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
if (!drop_temporary) if (!drop_temporary)
{ {
if ((error= wait_if_global_read_lock(thd, 0, 1))) if (!thd->locked_tables &&
{ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name);
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
else
need_start_waiters= TRUE;
}
/* /*
Acquire LOCK_open after wait_if_global_read_lock(). If we would hold Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
...@@ -1804,7 +1801,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, ...@@ -1804,7 +1801,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
thd->pop_internal_handler(); thd->pop_internal_handler();
if (need_start_waiters) if (need_start_waiting)
start_waiting_global_read_lock(thd); start_waiting_global_read_lock(thd);
if (error) if (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