• Konstantin Osipov's avatar
    Backport of: · 2f265740
    Konstantin Osipov authored
    ------------------------------------------------------------
    revno: 2617.68.7
    committer: Dmitry Lenev <dlenev@mysql.com>
    branch nick: mysql-next-bg46044
    timestamp: Thu 2009-08-27 10:22:17 +0400
    message:
      Fix for bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE HIGH_PRIORITY
      FOR UPDATE".
    
      Deadlock occured when during execution of query to I_S we tried to open
      a table or its .FRM in order to get information about it and had to wait
      because we have encountered exclusive metadata lock on this table held by
      a DDL operation from another connection which in its turn waited for some
      resource currently owned by connection executing this I_S query.
      For example, this might have happened if one under LOCK TABLES executed I_S
      query targeted to particular table (which was not among locked) and also
      concurrently tried to create this table using CREATE TABLE SELECT which
      had to wait for one of tables locked by the first connection.
      Another situation in which deadlock might have occured is when I_S query,
      which was executed as part of transaction, tried to get information about
      table which just has been dropped by concurrent DROP TABLES executed under
      LOCK TABLES and this DROP TABLES for its completion also had to wait
      transaction from the first connection.
    
      This problem stemmed from the fact that opening of tables/.FRMs for I_S
      filling is happening outside of connection's main MDL_context so code
      which tries to detect deadlocks due to conflicting metadata locks doesn't
      work in this case. Indeed, this led to deadlocks when during I_S filling
      we tried to wait for conflicting metadata lock to go away, while its owner
      was waiting for some resource held by connection executing I_S query.
    
      This patch solves this problem by avoiding waiting in such situation.
      Instead we skip this table and produce warning that information about
      it was omitted from I_S due to concurrent DDL operation. We still wait
      for conflicting metadata lock to go away when it is known that deadlock
      is not possible (i.e. when connection executing I_S query does not hold
      any metadata or table-level locks).
      Basically, we apply our standard deadlock avoidance technique for metadata
      locks to the process of filling of I_S tables but replace ER_LOCK_DEADLOCK
      error with a warning.
      Note that this change is supposed to be safe for 'mysqldump' since the
      only its mode which is affected by this change is --single-transaction mode
      is not safe in the presence of concurrent DDL anyway (and this fact is
      documented). Other modes are unaffected because they either use
      SHOW TABLES/SELECT * FROM I_S.TABLE_NAMES which do not take any metadata
      locks in the process of I_S table filling and thus cannot skip tables or
      execute I_S queries for tables which were previously locked by LOCK TABLES
      (or in the presence of global read lock) which excludes possibility of
      encountering conflicting metadata lock.
    
    
    mysql-test/r/mdl_sync.result:
      Added test for bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE
      HIGH_PRIORITY FOR UPDATE".
    mysql-test/t/mdl_sync.test:
      Added test for bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE
      HIGH_PRIORITY FOR UPDATE".
    sql/mysql_priv.h:
      Added a new flag for open_table() call which allows it to fail
      with an error in cases when conflicting metadata lock is discovered
      instead of waiting until this lock goes away.
    sql/share/errmsg-utf8.txt:
      Added error/warning message to be generated in cases when information
      about table is omitted from I_S since there is conflicting metadata lock
      on the table.
    sql/share/errmsg.txt:
      Added error/warning message to be generated in cases when information
      about table is omitted from I_S since there is conflicting metadata lock
      on the table.
    sql/sql_base.cc:
      Added a new flag for open_table() call which allows it to fail
      with an error in cases when conflicting metadata lock is discovered
      instead of waiting until this lock goes away.
    sql/sql_show.cc:
      When we are opening a table (or just .FRM) in order to fill I_S with
      information about this table and encounter conflicting metadata lock
      waiting for this lock to go away can lead to a deadlock in some
      situations (under LOCK TABLES, within transaction, etc.). To avoid
      these deadlocks we detect such situations and don't do waiting.
      Instead, we skip table for which we have conflicting metadata lock,
      thus omitting information about it from I_S table, and produce an
      appropriate warning.
    2f265740
sql_show.cc 250 KB