Skip to content

Commit

Permalink
Fixed hang in concurrent DROP TABLE and BACKUP LOCK BLOCK_DDL
Browse files Browse the repository at this point in the history
The problem was that tdc_remove_referenced_share() did not take into
account that someone could push things into share->free_tables() even
if there is a MDL_EXCLUSIVE lock on the table.
This can happen if flush_tables() uses the table cache to flush a
a non transactional table to disk.
  • Loading branch information
montywi authored and vuvova committed May 19, 2021
1 parent 0b59320 commit 744a538
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 1 deletion.
33 changes: 33 additions & 0 deletions mysql-test/suite/mariabackup/deadlock_drop_table.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
create or replace table t1 (a int primary key, b int, c int, key(b),key(c)) engine=myisam;
insert into t1 (a) values(1);
set debug_sync='RESET';
connect con1, localhost, root,,;
connect con2, localhost, root,,;
connection default;
backup stage start;
backup stage flush;
select * from t1;
a b c
1 NULL NULL
set debug_sync='after_purge_tables SIGNAL parked WAIT_FOR go';
set debug_sync='before_tc_release_table SIGNAL parked2 WAIT_FOR go2';
backup stage BLOCK_DDL;
connection con1;
set debug_sync='now WAIT_FOR parked';
select * from t1;
a b c
1 NULL NULL
set debug_sync='now SIGNAL go';
set debug_sync='now WAIT_FOR parked2';
set debug_sync='before_wait_for_refs SIGNAL waiting WAIT_FOR go3';
drop table t1;;
connection con2;
set debug_sync='now WAIT_FOR waiting';
set debug_sync='now SIGNAL go2';
set debug_sync='now SIGNAL go3';
connection default;
connection con1;
connection default;
disconnect con1;
disconnect con2;
set debug_sync='RESET';
35 changes: 35 additions & 0 deletions mysql-test/suite/mariabackup/deadlock_drop_table.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--source include/have_debug.inc

create or replace table t1 (a int primary key, b int, c int, key(b),key(c)) engine=myisam;
insert into t1 (a) values(1);

set debug_sync='RESET';
connect (con1, localhost, root,,);
connect (con2, localhost, root,,);
connection default;

backup stage start;
backup stage flush;
select * from t1;
set debug_sync='after_purge_tables SIGNAL parked WAIT_FOR go';
set debug_sync='before_tc_release_table SIGNAL parked2 WAIT_FOR go2';
--send backup stage BLOCK_DDL
--connection con1
set debug_sync='now WAIT_FOR parked';
select * from t1;
set debug_sync='now SIGNAL go';
set debug_sync='now WAIT_FOR parked2';
set debug_sync='before_wait_for_refs SIGNAL waiting WAIT_FOR go3';
--send drop table t1;
--connection con2
set debug_sync='now WAIT_FOR waiting';
set debug_sync='now SIGNAL go2';
set debug_sync='now SIGNAL go3';
--connection default
--reap
--connection con1
--reap
connection default;
disconnect con1;
disconnect con2;
set debug_sync='RESET';
2 changes: 2 additions & 0 deletions sql/sql_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ bool flush_tables(THD *thd, flush_tables_type flag)
DBUG_ENTER("flush_tables");

purge_tables(); /* Flush unused tables and shares */
DEBUG_SYNC(thd, "after_purge_tables");

/*
Loop over all shares and collect shares that have open tables
Expand Down Expand Up @@ -593,6 +594,7 @@ bool flush_tables(THD *thd, flush_tables_type flag)
if (table)
{
(void) table->file->extra(HA_EXTRA_FLUSH);
DEBUG_SYNC(table->in_use, "before_tc_release_table");
tc_release_table(table);
}
else
Expand Down
3 changes: 2 additions & 1 deletion sql/table_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1001,8 +1001,9 @@ void tdc_remove_referenced_share(THD *thd, TABLE_SHARE *share)
DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, share->db.str,
share->table_name.str,
MDL_EXCLUSIVE));
share->tdc->flush_unused(false);
share->tdc->flush_unused(true);
mysql_mutex_lock(&share->tdc->LOCK_table_share);
DEBUG_SYNC(thd, "before_wait_for_refs");
share->tdc->wait_for_refs(1);
DBUG_ASSERT(share->tdc->all_tables.is_empty());
share->tdc->ref_count--;
Expand Down

0 comments on commit 744a538

Please sign in to comment.