1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash

Version for 5.0.
It fixes three problems:
1. The cause of the bug was that we did not check the table version for
 the HANDLER ... READ commands. We did not notice when a table was
 replaced by a new one. This can happen during ALTER TABLE, REPAIR
 TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix
 for this problem "the primary bug fix".
2. mysql_ha_flush() was not always called with a locked LOCK_open.
 Though the function comment clearly said it must.
 I changed the code so that the locking is done when required. I call
 the fix for this problem "the secondary fix".
3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in
 concur with FLUSH TABLES WITH READ LOCK. I call the fix for this
 problem "the 5.0 addendum fix".


include/my_pthread.h:
  Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
  Added a new macro for the 5.0 addendum fix.
mysql-test/r/handler.result:
  Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
  The test result.
mysql-test/t/handler.test:
  Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
  The test case.
sql/lock.cc:
  Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
  Changed a comment which did confuse me and which is not fully
  correct anymore after the 5.0 addendum fix.
  Added an assertion which would fire without the 5.0 addendum fix.
sql/mysql_priv.h:
  Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
  Changed a definition for the secondary fix.
sql/sql_base.cc:
  Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
  Changed function calls for the secondary fix.
sql/sql_class.cc:
  Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
  Changed a function call for the secondary fix.
sql/sql_handler.cc:
  Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
  The first two diffs make the primary bug fix.
  The rest is for the secondary fix.
sql/sql_table.cc:
  Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
  The first diff (four changed places) make the 5.0 addendum fix.
  The other three are changed function calls for the secondary fix.
This commit is contained in:
unknown
2005-11-15 21:57:02 +01:00
parent d9c7aaf23f
commit 013b3d8ab3
9 changed files with 200 additions and 23 deletions

View File

@ -103,23 +103,28 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
/* mark for close and remove all cached entries */
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
VOID(pthread_mutex_lock(&LOCK_open));
if (!drop_temporary)
{
if ((error= wait_if_global_read_lock(thd, 0, 1)))
{
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name);
goto err;
DBUG_RETURN(TRUE);
}
else
need_start_waiters= TRUE;
}
/*
Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
LOCK_open during wait_if_global_read_lock(), other threads could not
close their tables. This would make a pretty deadlock.
*/
thd->mysys_var->current_mutex= &LOCK_open;
thd->mysys_var->current_cond= &COND_refresh;
VOID(pthread_mutex_lock(&LOCK_open));
error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
err:
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&thd->mysys_var->mutex);
@ -232,7 +237,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
char *db=table->db;
db_type table_type= DB_TYPE_UNKNOWN;
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL);
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, TRUE);
if (!close_temporary_table(thd, db, table->table_name))
{
tmp_table_deleted=1;
@ -2171,7 +2176,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL);
mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL, FALSE);
for (table= tables; table; table= table->next_local)
{
char table_name[NAME_LEN*2+2];
@ -3128,7 +3133,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
new_db= db;
used_fields=create_info->used_fields;
mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL);
mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL, FALSE);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,