• Dmitry Lenev's avatar
    Fix for bug #55273 "FLUSH TABLE tm WITH READ LOCK for Merge · 1a16ef1f
    Dmitry Lenev authored
    table causes assert failure".
    
    Attempting to use FLUSH TABLE table_list WITH READ LOCK
    statement for a MERGE table led to an assertion failure if
    one of its children was not present in the list of tables
    to be flushed. The problem was not visible in non-debug builds.
    
    The assertion failure was caused by the fact that in such
    situations FLUSH TABLES table_list WITH READ LOCK implementation
    tried to use (e.g. lock) such child tables without acquiring
    metadata lock on them. This happened because when opening tables
    we assumed metadata locks on all tables were already acquired
    earlier during statement execution and a such assumption was
    false for MERGE children.
    
    This patch fixes the problem by ensuring at open_tables() time
    that we try to acquire metadata locks on all tables to be opened. 
    For normal tables such requests are satisfied instantly since
    locks are already acquired for them. For MERGE children metadata
    locks are acquired in normal fashion.
    
    Note that FLUSH TABLES merge_table WITH READ LOCK will lock for
    read both the MERGE table and its children but will flush only 
    the MERGE table. To flush children one has to mention them in table
    list explicitly. This is expected behavior and it is consistent with
    usage patterns for this statement (e.g. in mysqlhotcopy script).
    
    mysql-test/r/flush.result:
      Added test case for bug #55273 "FLUSH TABLE tm WITH READ LOCK
      for Merge table causes assert failure".
    mysql-test/t/flush.test:
      Added test case for bug #55273 "FLUSH TABLE tm WITH READ LOCK
      for Merge table causes assert failure".
    sql/sql_base.cc:
      Changed lock_table_names() to support newly introduced
      MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK flag.
    sql/sql_base.h:
      Introduced MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK flag for
      open_tables() and lock_table_names() which allows to skip
      acquiring of global and schema-scope locks when SNW, SNRW or
      X metadata locks are acquired.
    sql/sql_reload.cc:
      Changed "FLUSH TABLES table_list WITH READ LOCK" code not to
      cause assert about missing metadata locks when MERGE table is
      flushed without one of its underlying tables.
      To achieve this we no longer call open_and_lock_tables() with
      MYSQL_OPEN_HAS_MDL_LOCK flag so this function automatically
      acquires metadata locks on MERGE children if such lock has
      not been already acquired at earlier stage. Instead we call
      this function with MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK flag to
      suppress acquiring of global IX lock in order to keep FLUSH
      TABLES  table_list WITH READ LOCK compatible with FLUSH TABLE
      WITH READ LOCK.
      Also changed implementation to use lock_table_names() function
      for pre-acquiring of metadata locks instead of custom code.
      To implement this change moved setting of open_type member for
      table list elements to parser.
    sql/sql_yacc.yy:
      Now we set acceptable type of table for FLUSH TABLES table_list
      WITH READ LOCK at parsing time instead of execution time.
    1a16ef1f
flush.test 13.9 KB