From 5196beed02b8bbd2758cd8c8ac11b6b0b711d390 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Wed, 17 Mar 2010 15:10:41 +0100 Subject: Bug#50561: ALTER PARTITIONS does not have adequate lock, breaks with concurrent I_S query There were two problem: 1) MYSQL_LOCK_IGNORE_FLUSH also ignored name locks 2) there was a race between abort_and_upgrade_locks and alter_close_tables (i.e. remove_table_from_cache and close_data_files_and_morph_locks) Which allowed the table to be opened with MYSQL_LOCK_IGNORE_FLUSH flag resulting in renaming a partition that was already in use, which could cause the table to be unusable. Solution was to not allow IGNORE_FLUSH to skip waiting for a named locked table. And to not release the LOCK_open mutex between the calls to remove_table_from_cache and close_data_files_and_morph_locks by merging the functions abort_and_upgrade_locks and alter_close_tables. mysql-test/suite/parts/r/partition_debug_sync_innodb.result: Bug#50561: ALTER PARTITIONS does not have adequate lock, breaks with concurrent I_S query Added test result mysql-test/suite/parts/t/partition_debug_sync_innodb-master.opt: Bug#50561: ALTER PARTITIONS does not have adequate lock, breaks with concurrent I_S query Added test option mysql-test/suite/parts/t/partition_debug_sync_innodb.test: Bug#50561: ALTER PARTITIONS does not have adequate lock, breaks with concurrent I_S query Added test file sql/authors.h: Bug#50561: ALTER PARTITIONS does not have adequate lock, breaks with concurrent I_S query Time to be acknowledged :) sql/ha_partition.cc: Bug#50561: ALTER PARTITIONS does not have adequate lock, breaks with concurrent I_S query Added DEBUG_SYNC for deterministic testing sql/mysql_priv.h: Bug#50561: ALTER PARTITIONS does not have adequate lock, breaks with concurrent I_S query Renamed function since merging alter_close_tables into abort_and_upgrade_lock. sql/sql_base.cc: Bug#50561: ALTER PARTITIONS does not have adequate lock, breaks with concurrent I_S query Changed MYSQL_LOCK_IGNORE_FLUSH to not ignore name locks (open_placeholder). Merged alter_close_tables into abort_and_upgrade_locks (and added _and_close_table to the name) to not release LOCK_open between remove_table_from_cache and close_data_files_and_morph_locks. Added DEBUG_SYNC for deterministic testing. sql/sql_partition.cc: Bug#50561: ALTER PARTITIONS does not have adequate lock, breaks with concurrent I_S query Removed alter_close_tables, (merged it into abort_and_upgrad_lock) so that LOCK_open never is released between remove_table_from_cache and close_data_files_and_morph_locks. sql/sql_show.cc: Bug#50561: ALTER PARTITIONS does not have adequate lock, breaks with concurrent I_S query Added DEBUG_SYNC for deterministic testing --- sql/sql_partition.cc | 38 +++----------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) (limited to 'sql/sql_partition.cc') diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 395156dcd63..679d23b49ad 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -5955,32 +5955,6 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) } } -/* - Unlock and close table before renaming and dropping partitions - SYNOPSIS - alter_close_tables() - lpt Struct carrying parameters - RETURN VALUES - 0 -*/ - -static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt) -{ - THD *thd= lpt->thd; - const char *db= lpt->db; - const char *table_name= lpt->table_name; - DBUG_ENTER("alter_close_tables"); - /* - We need to also unlock tables and close all handlers. - We set lock to zero to ensure we don't do this twice - and we set db_stat to zero to ensure we don't close twice. - */ - pthread_mutex_lock(&LOCK_open); - close_data_files_and_morph_locks(thd, db, table_name); - pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(0); -} - /* Handle errors for ALTER TABLE for partitioning @@ -6278,9 +6252,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, write_log_drop_partition(lpt) || ERROR_INJECT_CRASH("crash_drop_partition_3") || (not_completed= FALSE) || - abort_and_upgrade_lock(lpt) || /* Always returns 0 */ - ERROR_INJECT_CRASH("crash_drop_partition_4") || - alter_close_tables(lpt) || + abort_and_upgrade_lock_and_close_table(lpt) || ERROR_INJECT_CRASH("crash_drop_partition_5") || ((!thd->lex->no_write_to_binlog) && (write_bin_log(thd, FALSE, @@ -6345,9 +6317,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, ERROR_INJECT_CRASH("crash_add_partition_2") || mysql_change_partitions(lpt) || ERROR_INJECT_CRASH("crash_add_partition_3") || - abort_and_upgrade_lock(lpt) || /* Always returns 0 */ - ERROR_INJECT_CRASH("crash_add_partition_4") || - alter_close_tables(lpt) || + abort_and_upgrade_lock_and_close_table(lpt) || ERROR_INJECT_CRASH("crash_add_partition_5") || ((!thd->lex->no_write_to_binlog) && (write_bin_log(thd, FALSE, @@ -6435,9 +6405,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, write_log_final_change_partition(lpt) || ERROR_INJECT_CRASH("crash_change_partition_4") || (not_completed= FALSE) || - abort_and_upgrade_lock(lpt) || /* Always returns 0 */ - ERROR_INJECT_CRASH("crash_change_partition_5") || - alter_close_tables(lpt) || + abort_and_upgrade_lock_and_close_table(lpt) || ERROR_INJECT_CRASH("crash_change_partition_6") || ((!thd->lex->no_write_to_binlog) && (write_bin_log(thd, FALSE, -- cgit v1.2.1