From 3bbba834071dfbad3317efee53de3c3270e70e7b Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 10 Oct 2008 17:14:39 +0300 Subject: [PATCH] Fix for bug#39226 Maria: crash with FLUSH TABLES WITH READ LOCK after LOCK TABLES The problem was that we didn't inform the handler that we are going to close tables that are locked and may have (at least in Maria) be part of an active transaction. Fix for Bug#39227 Maria: crash with ALTER TABLE PARTITION include/my_base.h: Added HA_EXTRA_PREPARE_FOR_FORCED_CLOSE for signaling the handler that the file will be forced closed mysql-test/r/maria.result: Test cases for bugs fixed mysql-test/t/maria.test: Test cases for bugs fixed sql/ha_partition.cc: Added support for the new extra flag: HA_EXTRA_PREPARE_FOR_FORCED_CLOSE (Bug #39226) Ensure that we call extra() for HA_EXTRA_PREPARE_FOR_DROP (Bug#39227) sql/sql_base.cc: Call HA_EXTRA_PREPARE_FOR_FORCED_CLOSE for tables that are locked but we are going to force close without doing a commit storage/maria/ma_extra.c: If HA_EXTRA_PREPARE_FOR_FORCED_CLOSE is called and the table is part of a transaction, remove the table from beeing part of a transaction. This is safe as this is only used as part of flush tables or when the table is not part of a transaction --- include/my_base.h | 4 +++- mysql-test/r/maria.result | 11 +++++++++++ mysql-test/t/maria.test | 20 ++++++++++++++++++++ sql/ha_partition.cc | 8 ++++---- sql/sql_base.cc | 5 +++++ storage/maria/ma_extra.c | 10 ++++++++++ 6 files changed, 53 insertions(+), 5 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index 3d7e8e1e60b..a2079f6745c 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -195,7 +195,9 @@ enum ha_extra_function { begin and end of a statement. */ HA_EXTRA_ATTACH_CHILDREN, - HA_EXTRA_DETACH_CHILDREN + HA_EXTRA_DETACH_CHILDREN, + /* Inform handler we will force a close as part of flush */ + HA_EXTRA_PREPARE_FOR_FORCED_CLOSE }; /* Compatible option, to be deleted in 6.0 */ diff --git a/mysql-test/r/maria.result b/mysql-test/r/maria.result index fb8537551c8..3907f4d8928 100644 --- a/mysql-test/r/maria.result +++ b/mysql-test/r/maria.result @@ -2284,3 +2284,14 @@ insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10; insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10; drop table t1,t2; drop view v1; +create table t1 (s1 int); +insert into t1 values (1); +alter table t1 partition by list (s1) (partition p1 values in (2)); +ERROR HY000: Table has no partition for value 1 +drop table t1; +create table t1 (c1 int); +create table t2 (c1 int); +lock table t1 read, t2 read; +flush tables with read lock; +unlock tables; +drop table t1, t2; diff --git a/mysql-test/t/maria.test b/mysql-test/t/maria.test index e35276f698d..bf2506472ae 100644 --- a/mysql-test/t/maria.test +++ b/mysql-test/t/maria.test @@ -1575,3 +1575,23 @@ insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10; insert into v1 (f1) values (3) on duplicate key update f1= f3 + 10; drop table t1,t2; drop view v1; + +# +# Bug #39227 Maria: crash with ALTER TABLE PARTITION +# + +create table t1 (s1 int); +insert into t1 values (1); +--error ER_NO_PARTITION_FOR_GIVEN_VALUE +alter table t1 partition by list (s1) (partition p1 values in (2)); +drop table t1; + +# +# Bug #39226 Maria: crash with FLUSH TABLES WITH READ LOCK after LOCK TABLES + +create table t1 (c1 int); +create table t2 (c1 int); +lock table t1 read, t2 read; +flush tables with read lock; +unlock tables; +drop table t1, t2; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b239253fbc7..1acdca9d8e7 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4935,6 +4935,7 @@ int ha_partition::extra(enum ha_extra_function operation) case HA_EXTRA_KEYREAD: case HA_EXTRA_NO_KEYREAD: case HA_EXTRA_FLUSH: + case HA_EXTRA_PREPARE_FOR_FORCED_CLOSE: DBUG_RETURN(loop_extra(operation)); /* Category 2), used by non-MyISAM handlers */ @@ -4958,8 +4959,7 @@ int ha_partition::extra(enum ha_extra_function operation) case HA_EXTRA_PREPARE_FOR_DROP: case HA_EXTRA_FLUSH_CACHE: { - if (m_myisam) - DBUG_RETURN(loop_extra(operation)); + DBUG_RETURN(loop_extra(operation)); break; } case HA_EXTRA_CACHE: @@ -5153,8 +5153,8 @@ int ha_partition::loop_extra(enum ha_extra_function operation) DBUG_ENTER("ha_partition::loop_extra()"); /* - TODO, 5.2: this is where you could possibly add optimisations to add the bitmap - _if_ a SELECT. + TODO, 5.2: this is where you could possibly add optimisations to add the + bitmap _if_ a SELECT. */ for (file= m_file; *file; file++) { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 34395332118..2d9dabcd4fe 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3508,6 +3508,11 @@ static void close_old_data_files(THD *thd, TABLE *table, bool morph_locks, TABLE *ulcktbl= table->parent ? table->parent : table; if (ulcktbl->lock_count) { + /* + Inform handler that we will do a close even if the table may be + locked or part of a transaction + */ + table->file->extra(HA_EXTRA_PREPARE_FOR_FORCED_CLOSE); /* Wake up threads waiting for table-level lock on this table so they won't sneak in when we will temporarily remove our diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index 7fab28edf42..301d3af3549 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -371,6 +371,16 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, pthread_mutex_unlock(&THR_LOCK_maria); break; } + case HA_EXTRA_PREPARE_FOR_FORCED_CLOSE: + if (info->trn) + { + pthread_mutex_lock(&share->intern_lock); + _ma_remove_table_from_trnman(share, info->trn); + /* Ensure we don't point to the deleted data in trn */ + info->state= info->state_start= &share->state.state; + pthread_mutex_unlock(&share->intern_lock); + } + break; case HA_EXTRA_FLUSH: if (!share->temporary) error= _ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,