• Monty's avatar
    MDEV-11412 Ensure that table is truly dropped when using DROP TABLE · 5bcb1d65
    Monty authored
    The used code is largely based on code from Tencent
    
    The problem is that in some rare cases there may be a conflict between .frm
    files and the files in the storage engine. In this case the DROP TABLE
    was not able to properly drop the table.
    
    Some MariaDB/MySQL forks has solved this by adding a FORCE option to
    DROP TABLE. After some discussion among MariaDB developers, we concluded
    that users expects that DROP TABLE should always work, even if the
    table would not be consistent. There should not be a need to use a
    separate keyword to ensure that the table is really deleted.
    
    The used solution is:
    - If a .frm table doesn't exists, try dropping the table from all storage
      engines.
    - If the .frm table exists but the table does not exist in the engine
      try dropping the table from all storage engines.
    - Update storage engines using many table files (.CVS, MyISAM, Aria) to
      succeed with the drop even if some of the files are missing.
    - Add HTON_AUTOMATIC_DELETE_TABLE to handlerton's where delete_table()
      is not needed and always succeed. This is used by ha_delete_table_force()
      to know which handlers to ignore when trying to drop a table without
      a .frm file.
    
    The disadvantage of this solution is that a DROP TABLE on a non existing
    table will be a bit slower as we have to ask all active storage engines
    if they know anything about the table.
    
    Other things:
    - Added a new flag MY_IGNORE_ENOENT to my_delete() to not give an error
      if the file doesn't exist. This simplifies some of the code.
    - Don't clear thd->error in ha_delete_table() if there was an active
      error. This is a bug fix.
    - handler::delete_table() will not abort if first file doesn't exists.
      This is bug fix to handle the case when a drop table was aborted in
      the middle.
    - Cleaned up mysql_rm_table_no_locks() to ensure that if_exists uses
      same code path as when it's not used.
    - Use non_existing_Table_error() to detect if table didn't exists.
      Old code used different errors tests in different position.
    - Table_triggers_list::drop_all_triggers() now drops trigger file if
      it can't be parsed instead of leaving it hanging around (bug fix)
    - InnoDB doesn't anymore print error about .frm file out of sync with
      InnoDB directory if .frm file does not exists. This change was required
      to be able to try to drop an InnoDB file when .frm doesn't exists.
    - Fixed bug in mi_delete_table() where the .MYD file would not be dropped
      if the .MYI file didn't exists.
    - Fixed memory leak in Mroonga when deleting non existing table
    - Fixed memory leak in Connect when deleting non existing table
    
    Bugs fixed introduced by the original version of this commit:
    MDEV-22826 Presence of Spider prevents tables from being force-deleted from
               other engines
    5bcb1d65
log.cc 329 KB