Commit 5ca6880d authored by Dmitry Shulga's avatar Dmitry Shulga

Fixed bug#54486 - assert in my_seek, concurrent

DROP/CREATE SCHEMA, CREATE TABLE, REPAIR.

The cause of assert was concurrent execution of
DROP DATABASE and REPAIR TABLE where first statement
deleted table's file .TMD at the same time as
REPAIR TABLE tried to read file details from the old file
that was just removed.

Additionally was fixed trouble when DROP TABLE try delete
all files belong to table being dropped at the same time
when REPAIR TABLE statement has just deleted .TMD file.

No regression test added because this would require adding a
sync point to mysys/my_redel.c. Since this bug is not present in
5.5+, adding test coverage was considered unnecessary.
The patch has been verified using RQG testing.


sql/sql_db.cc:
  mysql_rm_known_files() modified: ignore possible ENOENT error
  when trying delete all table's files. Such aggressive 
  algorithm permits skip already deleted (in another thread)
  files.
  
  Installation of Drop_table_error_handler as internal error handler
  moved from mysql_rm_db() to mysql_rm_knowns_files() near to place
  where source of possible errors (call to mysql_rm_table_part2) located.
storage/myisam/mi_check.c:
  mi_repair() was modified: set param->retry_repair= 0
  in order to don't call following failover procedure
  in ha_myisam::repair().
parent 50d1f9f3
...@@ -948,9 +948,6 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) ...@@ -948,9 +948,6 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
remove_db_from_cache(db); remove_db_from_cache(db);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
Drop_table_error_handler err_handler(thd->get_internal_handler());
thd->push_internal_handler(&err_handler);
error= -1; error= -1;
/* /*
We temporarily disable the binary log while dropping the objects We temporarily disable the binary log while dropping the objects
...@@ -983,8 +980,8 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) ...@@ -983,8 +980,8 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
error = 0; error = 0;
reenable_binlog(thd); reenable_binlog(thd);
} }
thd->pop_internal_handler();
} }
if (!silent && deleted>=0) if (!silent && deleted>=0)
{ {
const char *query; const char *query;
...@@ -1213,16 +1210,34 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, ...@@ -1213,16 +1210,34 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
else else
{ {
strxmov(filePath, org_path, "/", file->name, NullS); strxmov(filePath, org_path, "/", file->name, NullS);
if (my_delete_with_symlink(filePath,MYF(MY_WME))) /*
We ignore ENOENT error in order to skip files that was deleted
by concurrently running statement like REAPIR TABLE ...
*/
if (my_delete_with_symlink(filePath, MYF(0)) &&
my_errno != ENOENT)
{ {
goto err; my_error(EE_DELETE, MYF(0), filePath, my_errno);
goto err;
} }
} }
} }
if (thd->killed ||
(tot_list && mysql_rm_table_part2(thd, tot_list, 1, 0, 1, 1))) if (thd->killed)
goto err; goto err;
if (tot_list)
{
int res= 0;
Drop_table_error_handler err_handler(thd->get_internal_handler());
thd->push_internal_handler(&err_handler);
res= mysql_rm_table_part2(thd, tot_list, 1, 0, 1, 1);
thd->pop_internal_handler();
if (res)
goto err;
}
/* Remove RAID directories */ /* Remove RAID directories */
{ {
List_iterator<String> it(raid_dirs); List_iterator<String> it(raid_dirs);
......
...@@ -1741,6 +1741,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1741,6 +1741,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
mi_open_datafile(info,share,name,-1)) mi_open_datafile(info,share,name,-1))
got_error=1; got_error=1;
param->retry_repair= 0;
} }
} }
if (got_error) if (got_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