• istruewing@stella.local's avatar
    Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE · 06052741
    istruewing@stella.local authored
                corrupts a MERGE table
    Bug 26867 - LOCK TABLES + REPAIR + merge table result in
                memory/cpu hogging
    Bug 26377 - Deadlock with MERGE and FLUSH TABLE
    Bug 25038 - Waiting TRUNCATE
    Bug 25700 - merge base tables get corrupted by
                optimize/analyze/repair table
    Bug 30275 - Merge tables: flush tables or unlock tables
                causes server to crash
    Bug 19627 - temporary merge table locking
    Bug 27660 - Falcon: merge table possible
    Bug 30273 - merge tables: Can't lock file (errno: 155)
    
    The problems were:
    
    Bug 26379 - Combination of FLUSH TABLE and REPAIR TABLE
                    corrupts a MERGE table
    
      1. A thread trying to lock a MERGE table performs busy waiting while
         REPAIR TABLE or a similar table administration task is ongoing on
         one or more of its MyISAM tables.
      
      2. A thread trying to lock a MERGE table performs busy waiting until all
         threads that did REPAIR TABLE or similar table administration tasks
         on one or more of its MyISAM tables in LOCK TABLES segments do UNLOCK
         TABLES. The difference against problem #1 is that the busy waiting
         takes place *after* the administration task. It is terminated by
         UNLOCK TABLES only.
      
      3. Two FLUSH TABLES within a LOCK TABLES segment can invalidate the
         lock. This does *not* require a MERGE table. The first FLUSH TABLES
         can be replaced by any statement that requires other threads to
         reopen the table. In 5.0 and 5.1 a single FLUSH TABLES can provoke
         the problem.
    
    Bug 26867 - LOCK TABLES + REPAIR + merge table result in
                memory/cpu hogging
    
      Trying DML on a MERGE table, which has a child locked and
      repaired by another thread, made an infinite loop in the server.
    
    Bug 26377 - Deadlock with MERGE and FLUSH TABLE
    
      Locking a MERGE table and its children in parent-child order
      and flushing the child deadlocked the server.
    
    Bug 25038 - Waiting TRUNCATE
    
      Truncating a MERGE child, while the MERGE table was in use,
      let the truncate fail instead of waiting for the table to
      become free.
    
    Bug 25700 - merge base tables get corrupted by
                optimize/analyze/repair table
    
      Repairing a child of an open MERGE table corrupted the child.
      It was necessary to FLUSH the child first.
    
    Bug 30275 - Merge tables: flush tables or unlock tables
                causes server to crash
    
      Flushing and optimizing locked MERGE children crashed the server.
    
    Bug 19627 - temporary merge table locking
    
      Use of a temporary MERGE table with non-temporary children
      could corrupt the children.
    
      Temporary tables are never locked. So we do now prohibit
      non-temporary chidlren of a temporary MERGE table.
    
    Bug 27660 - Falcon: merge table possible
    
      It was possible to create a MERGE table with non-MyISAM children.
    
    Bug 30273 - merge tables: Can't lock file (errno: 155)
    
      This was a Windows-only bug. Table administration statements
      sometimes failed with "Can't lock file (errno: 155)".
    
    These bugs are fixed by a new implementation of MERGE table open.
    
    When opening a MERGE table in open_tables() we do now add the
    child tables to the list of tables to be opened by open_tables()
    (the "query_list"). The children are not opened in the handler at
    this stage.
    
    After opening the parent, open_tables() opens each child from the
    now extended query_list. When the last child is opened, we remove
    the children from the query_list again and attach the children to
    the parent. This behaves similar to the old open. However it does
    not open the MyISAM tables directly, but grabs them from the already
    open children.
    
    When closing a MERGE table in close_thread_table() we detach the
    children only. Closing of the children is done implicitly because
    they are in thd->open_tables.
    
    For more detail see the comment at the top of ha_myisammrg.cc.
    
    Changed from open_ltable() to open_and_lock_tables() in all places
    that can be relevant for MERGE tables. The latter can handle tables
    added to the list on the fly. When open_ltable() was used in a loop
    over a list of tables, the list must be temporarily terminated
    after every table for open_and_lock_tables().
    table_list->required_type is set to FRMTYPE_TABLE to avoid open of
    special tables. Handling of derived tables is suppressed.
    These details are handled by the new function
    open_n_lock_single_table(), which has nearly the same signature as
    open_ltable() and can replace it in most cases.
    
    In reopen_tables() some of the tables open by a thread can be
    closed and reopened. When a MERGE child is affected, the parent
    must be closed and reopened too. Closing of the parent is forced
    before the first child is closed. Reopen happens in the order of
    thd->open_tables. MERGE parents do not attach their children
    automatically at open. This is done after all tables are reopened.
    So all children are open when attaching them.
    
    Special lock handling like mysql_lock_abort() or mysql_lock_remove()
    needs to be suppressed for MERGE children or forwarded to the parent.
    This depends on the situation. In loops over all open tables one
    suppresses child lock handling. When a single table is touched,
    forwarding is done.
    
    Behavioral changes:
    ===================
    
    This patch changes the behavior of temporary MERGE tables.
    Temporary MERGE must have temporary children.
    The old behavior was wrong. A temporary table is not locked. Hence
    even non-temporary children were not locked. See
    Bug 19627 - temporary merge table locking.
    
    You cannot change the union list of a non-temporary MERGE table
    when LOCK TABLES is in effect. The following does *not* work:
    CREATE TABLE m1 ... ENGINE=MRG_MYISAM ...;
    LOCK TABLES t1 WRITE, t2 WRITE, m1 WRITE;
    ALTER TABLE m1 ... UNION=(t1,t2) ...;
    However, you can do this with a temporary MERGE table.
    
    You cannot create a MERGE table with CREATE ... SELECT, neither
    as a temporary MERGE table, nor as a non-temporary MERGE table.
    CREATE TABLE m1 ... ENGINE=MRG_MYISAM ... SELECT ...;
    Gives error message: table is not BASE TABLE.
    06052741
sql_table.cc 224 KB