Bug #52044 FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompati
Submitted: 14 Mar 2010 8:59 Modified: 30 Dec 2010 18:59
Reporter: Konstantin Osipov (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Locking Severity:S3 (Non-critical)
Version:5.5.3-m3 OS:Any
Assigned to: Dmitry Lenev CPU Architecture:Any

[14 Mar 2010 8:59] Konstantin Osipov
Description:
5.5.3-m3 features a new FLUSH TABLES syntax, FLUSH TABLES <list> WITH READ LOCK.

The trouble is that FLUSH TABLES <list> WITH READ LOCK is not compatible (is mutually exclusive) with FLUSH TABLES WITH READ LOCK.

I.e. one can issue:

con1:                                con2:
FLUSH TABLES WITH READ LOCK;         FLUSH TABLES WITH READ LOCK;

One can issue:

con1:                                con2:
FLUSH TABLES t1 WITH READ LOCK;      FLUSH TABLES t2 WITH READ LOCK;

But this is currently not possible:

con1:                                con2:
FLUSH TABLES WITH READ LOCK          FLUSH TABLES t1 WITH READ LOCK (blocks).

The order is not important, if con2 comes first, con1 blocks, and vice versa.

How to repeat:
See description: open two connection, try FLUSH TABLES WITH READ LOCK in one, FLUSH TABLES <list> WITH READ LOCK in another.
[14 Mar 2010 16:43] MySQL Verification Team
Thank you for the bug report.
[12 Jul 2010 16:36] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/113375

3078 Dmitry Lenev	2010-07-12
      A pre-requisite for patch fixing bug #52044 "FLUSH TABLES 
      WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are
      incompatible", which adds information about waits caused by 
      FLUSH TABLES statement to deadlock detector in MDL subsystem.
      
      Remove API supporting caching of pointers to TABLE_SHARE 
      object in MDL subsystem and all code related to it. 
      
      The problem was that locking requirements of code 
      implementing this API conflicted with locking requirements 
      of code which adds information about waits caused by flushes 
      to deadlock detector in MDL subsystem (the former needed to
      lock LOCK_open or its future equivalent while having 
      write-lock on MDL_lock's rwlock, and the latter needs to be 
      able to read-lock MDL_lock rwlock while owning LOCK_open or 
      its future equivalent).
      
      Since caching of pointers to TABLE_SHARE objects in MDL 
      subsystem didn't bring expected performance benefits we 
      decided to remove caching API rather than try to come up 
      with some complex solution for this problem.
[13 Jul 2010 18:02] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/113499

3079 Dmitry Lenev	2010-07-13
      A pre-requisite for patch fixing bug #52044 "FLUSH TABLES 
      WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are
      incompatible", which adds information about waits caused by 
      FLUSH TABLES statement to deadlock detector in MDL subsystem.
      
      Remove API supporting caching of pointers to TABLE_SHARE 
      object in MDL subsystem and all code related to it. 
      
      The problem was that locking requirements of code 
      implementing this API conflicted with locking requirements 
      of code which adds information about waits caused by flushes 
      to deadlock detector in MDL subsystem (the former needed to
      lock LOCK_open or its future equivalent while having 
      write-lock on MDL_lock's rwlock, and the latter needs to be 
      able to read-lock MDL_lock rwlock while owning LOCK_open or 
      its future equivalent).
      
      Since caching of pointers to TABLE_SHARE objects in MDL 
      subsystem didn't bring expected performance benefits we 
      decided to remove caching API rather than try to come up 
      with some complex solution for this problem.
[14 Jul 2010 20:04] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/113634

3080 Dmitry Lenev	2010-07-15
      Fix for bug #52044 "FLUSH TABLES WITH READ LOCK and FLUSH
      TABLES <list> WITH READ LOCK are incompatible".
      
      The problem was that FLUSH TABLES <list> WITH READ LOCK
      which was issued when other connection has acquired global
      read lock using FLUSH TABLES WITH READ LOCK was blocked
      and has to wait until global read lock is released.
      
      This issue stemmed from the fact that FLUSH TABLES <list>
      WITH READ LOCK implementation has acquired X metadata locks
      on tables to be flushed. Since these locks required acquiring
      of global IX lock this statement was incompatible with global
      read lock.
      
      This patch addresses problem by using SNW metadata type of
      lock for tables to be flushed by FLUSH TABLES <list> WITH
      READ LOCK. It is OK to acquire them without global IX lock
      as long as we won't try to upgrade those locks. Since SNW
      locks allow concurrent statements using same table FLUSH
      TABLE <list> WITH READ LOCK now has to wait until old
      versions of tables to be flushed go away after acquiring
      metadata locks. Since such waiting can lead to deadlock
      MDL deadlock detector was extended to take into account
      waits for flush and resolve such deadlocks.
      
      As a bonus code in open_tables() which was responsible for
      waiting old versions of tables to go away was refactored.
      Now when we encounter old version of table in open_table()
      we don't back-off and wait for all old version to go away,
      but instead wait for this particular table to be flushed.
      Such approach supported by deadlock detection should reduce
      number of scenarios in which FLUSH TABLES aborts concurrent
      multi-statement transactions.
      
      Note that active FLUSH TABLES <list> WITH READ LOCK still
      blocks concurrent FLUSH TABLES WITH READ LOCK statement
      as the former keeps tables open and thus prevents the
      latter statement from doing flush.
     @ mysql-test/include/handler.inc
        Adjusted test case after changing status which is set
        when FLUSH TABLES waits for tables to be flushed from
        "Flushing tables" to "Waiting for table".
     @ mysql-test/r/flush.result
        Added test which checks that "flush tables <list> with
        read lock" is compatible with active "flush tables with
        read lock" but not vice-versa. This test also covers
        bug #52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES
        <list> WITH READ LOCK are incompatible".
     @ mysql-test/r/mdl_sync.result
        Added scenarios in which wait for table to be flushed
        causes deadlocks to the coverage of MDL deadlock detector.
     @ mysql-test/suite/perfschema/r/dml_setup_instruments.result
        Adjusted test results after removal of COND_refresh
        condition variable.
     @ mysql-test/suite/perfschema/r/server_init.result
        Adjusted test and its results after removal of COND_refresh
        condition variable.
     @ mysql-test/suite/perfschema/t/server_init.test
        Adjusted test and its results after removal of COND_refresh
        condition variable.
     @ mysql-test/t/flush.test
        Added test which checks that "flush tables <list> with
        read lock" is compatible with active "flush tables with
        read lock" but not vice-versa. This test also covers
        bug #52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES
        <list> WITH READ LOCK are incompatible".
     @ mysql-test/t/kill.test
        Adjusted test case after changing status which is set
        when FLUSH TABLES waits for tables to be flushed from
        "Flushing tables" to "Waiting for table".
     @ mysql-test/t/lock_multi.test
        Adjusted test case after changing status which is set
        when FLUSH TABLES waits for tables to be flushed from
        "Flushing tables" to "Waiting for table".
     @ mysql-test/t/mdl_sync.test
        Added scenarios in which wait for table to be flushed
        causes deadlocks to the coverage of MDL deadlock detector.
     @ sql/ha_ndbcluster.cc
        Adjusted code after adding one more parameter for
        close_cached_tables() call - timeout for waiting for
        table to be flushed.
     @ sql/ha_ndbcluster_binlog.cc
        Adjusted code after adding one more parameter for
        close_cached_tables() call - timeout for waiting for
        table to be flushed.
     @ sql/lock.cc
        Removed COND_refresh condition variable. See comment
        for sql_base.cc for details.
     @ sql/mdl.cc
        Now MDL deadlock detector takes into account information
        about waits for table flushes when searching for deadlock.
        To implement this change:
        - Declaration of enum_deadlock_weight and
          Deadlock_detection_visitor were moved to mdl.h header
          to make them available to the code in table.cc which
          implements deadlock detector traversal through edges
          of waiters graph representing waiting for flush.
        - Since now MDL_context may wait not only for metadata
          lock but also for table to be flushed an abstract
          Wait_for_edge class was introduced. Its descendants
          MDL_ticket and Flush_ticket incapsulate specifics
          of inspecting waiters graph when following through
          edge representing wait of particular type.
        
        We no longer require global IX metadata lock when acquiring
        SNW or SNRW locks. Such locks are needed only when metadata
        locks of these types are upgraded to X locks. This allows
        to use SNW locks in FLUSH TABLES <list> WITH READ LOCK
        implementation and keep the latter compatible with global
        read lock.
     @ sql/mdl.h
        Now MDL deadlock detector takes into account information
        about waits for table flushes when searching for deadlock.
        To implement this change:
        - Declaration of enum_deadlock_weight and
          Deadlock_detection_visitor were moved to mdl.h header
          to make them available to the code in table.cc which
          implements deadlock detector traversal through edges
          of waiters graph representing waiting for flush.
        - Since now MDL_context may wait not only for metadata
          lock but also for table to be flushed an abstract
          Wait_for_edge class was introduced. Its descendants
          MDL_ticket and Flush_ticket incapsulate specifics
          of inspecting waiters graph when following through
          edge representing wait of particular type.
        - Deadlock_detection_visitor now has m_table_shares_visited
          member which allows to support recursive locking for
          LOCK_open. This is required when deadlock detector
          inspects waiters graph which contains several edges
          representing waits for flushes or needs to come through
          the such edge more than once.
     @ sql/mysqld.cc
        Removed COND_refresh condition variable. See comment
        for sql_base.cc for details.
     @ sql/mysqld.h
        Removed COND_refresh condition variable. See comment
        for sql_base.cc for details.
     @ sql/sql_base.cc
        Changed approach to how threads are waiting for table
        to be flushed. Now thread that wants to wait for old
        table to go away subscribes for notification by adding
        Flush_ticket to table's share and waits using
        MDL_context::m_wait object. Once table gets flushed
        (i.e. all tables are closed and table share is ready
        to be destroyed) all such waiters are notified
        individually.
        Thanks to this change MDL deadlock detector can take
        such waits into account.
        
        To implement this/as result of this change:
        - tdc_wait_for_old_versions() was replaced with
          tdc_wait_for_old_version() which waits for individual
          old share to go away and which is called by open_table()
          after finding out that share is outdated. We don't
          need to perform back-off before such waiting thanks
          to the fact that deadlock detector now sees such waits.
        - As result Open_table_ctx::m_mdl_requests became
          unnecessary and was removed. We no longer allocate
          copies of MDL_request objects on MEM_ROOT when
          MYSQL_OPEN_FORCE_SHARED/SHARED_HIGH_PRIO flags are
          in effect.
        - close_cached_tables() and tdc_wait_for_old_version()
          share code which implements waiting for share to be
          flushed - the both use TABLE_SHARE::wait_until_flush()
          method. Thanks to this close_cached_tables() supports
          timeouts and has extra parameter for this.
        - Open_table_context::OT_MDL_CONFLICT enum element was
          renamed to OT_CONFLICT as it is now also used in cases
          when back-off is required to resolve deadlock caused
          by waiting for flush and not metadata lock.
        - In cases when we discover that current connection tries
          to open tables from different generation we now simply
          back-off and restart process of opening tables. To
          support this Open_table_context::OT_REOPEN_TABLES enum
          element was added.
        - COND_refresh condition variable became unnecessary and
          was removed.
        - mysql_notify_thread_having_shared_lock() no longer wakes
          up connections waiting for flush as all such connections
          can be waken up by deadlock detector if necessary.
        
        close_thread_table() was temporarily changed to support
        optional release of metadata locks even in autocommit
        mode. This is a workaround which allows to solve problem
        with early release of metadata locks if back-off happens
        during FLUSH TABLES <list> WITH READ LOCK problem.
     @ sql/sql_base.h
        - close_thread_table() was temporarily changed to support
          optional release of metadata locks even in autocommit
          mode. This is a workaround which allows to solve problem
          with early release of metadata locks if back-off happens
          during FLUSH TABLES <list> WITH READ LOCK problem.
        - close_cached_tables() now has one more parameter -
          timeout for waiting for table to be flushed.
        - Open_table_context::OT_MDL_CONFLICT enum element was
          renamed to OT_CONFLICT as it is now also used in cases
          when back-off is required to resolve deadlock caused
          by waiting for flush and not metadata lock.
          Added new OT_REOPEN_TABLES enum element to be used in
          cases when we need to restart open tables process even
          in the middle of transaction.
        - Open_table_ctx::m_mdl_requests became unnecessary and
          was removed.
     @ sql/sql_class.h
        Added assert ensuring that we won't use LOCK_open mutex
        with THD::enter_cond(). Otherwise deadlocks can arise in
        MDL deadlock detector.
     @ sql/sql_parse.cc
        Changed FLUSH TABLES <list> WITH READ LOCK to take SNW
        metadata locks instead of X locks on tables to be flushed.
        Since we no longer require global IX lock to be taken
        when SNW locks are taken this makes this statement
        compatible with FLUSH TABLES WITH READ LOCK statement.
        Since SNW locks allow other connections to have table
        opened FLUSH TABLES <list> WITH READ LOCK now has to
        wait during open_tables() for old version to go away.
        Such waits can lead to deadlocks which will be detected
        by MDL deadlock detector which now takes waits for table
        to be flushed into account.
        
        Also adjusted code after adding one more parameter for
        close_cached_tables() call - timeout for waiting for
        table to be flushed.
     @ sql/sql_table.cc
        Removed COND_refresh condition variable. See comment
        for sql_base.cc for details.
     @ sql/sql_yacc.yy
        FLUSH TABLES <list> WITH READ LOCK now needs only SNW
        metadata locks on tables.
     @ sql/sys_vars.cc
        - close_thread_table() was temporarily changed to support
          optional release of metadata locks even in autocommit
          mode.
        - Adjusted code after adding one more parameter for
          close_cached_tables() call - timeout for waiting for
          table to be flushed.
     @ sql/table.cc
        Implemented new approach to how threads are waiting for
        table to be flushed. Now thread that wants to wait for
        old table to go away subscribes for notification by
        adding Flush_ticket to table's share and waits using
        MDL_context::m_wait object. Once table gets flushed
        (i.e. all tables are closed and table share is ready
        to be destroyed) all such waiters are notified
        individually. This change allows to make such waits
        visible inside of MDL deadlock detector.
        To do it:
        
        - Added list of waiters/Flush_tickets to TABLE_SHARE
          class.
        - Changed free_table_share() to postpone freeing of
          share memory until last waiter goes away and to
          wake up subscribed waiters.
        - Added TABLE_SHARE::wait_until_flushed() method which
          implements subscription to the list of waiters for
          table to be flushed and waiting for this event.
        
        Implemented interface which allows to expose waits for
        flushes to MDL deadlock detector:
        
        - Introduced Flush_ticket class a descendant of
          Wait_for_edge class.
        - Added TABLE_SHARE::find_deadlock() method which allows
          deadlock detector to find out what contexts are still
          using old version of table in question (i.e. to find
          out what contexts are waited for by owner of
          Flush_ticket).
     @ sql/table.h
        In order to support new strategy of waiting for table flush
        (see comment for table.cc for details) added list of
        waiters/Flush_tickets to TABLE_SHARE class.
        
        Implemented interface which allows to expose waits for
        flushes to MDL deadlock detector:
        - Introduced Flush_ticket class a descendant of
          Wait_for_edge class.
        - Added TABLE_SHARE::find_deadlock() method which allows
          deadlock detector to find out what contexts are still
          using old version of table in question (i.e. to find
          out what contexts are waited for by owner of
          Flush_ticket).
     @ sql/tztime.cc
        close_thread_table() was temporarily changed to support
        optional release of metadata locks even in autocommit mode.
[21 Jul 2010 13:44] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/114039

3079 Konstantin Osipov	2010-07-21
      A pre-requisite patch for the fix for Bug#52044.
      ******
      Cleanup COM_FIELD_LIST.
      Don't call close_thread_tables() in COM_SHUTDOWN -- there
      are no open tables there that can be closed (we leave
      the locked tables mode in THD destructor, and this
      close_thread_tables() won't leave it anyway).
      ******
      Make open_and_lock_tables() close thread table in case it fails.
      Remove the calls to close_thread_tables that are now unnecessary.
      ******
      Remove the release of metadata locks
      from close_thread_tables().
      ******
      Simplify the back off condition.
      ******
      Move statement commit outside 
      close_thread_tables().
      ******
      Streamline metadata lock handling in LOCK TABLES 
      implementation.
      Add asserts.
     @ mysql-test/r/view.result
        A harmless change in CHECK TABLE <view> status for a broken view.
        If previously a failure to prelock all functions used in a view 
        would leave the connection in LTM_PRELOCKED mode, now we call
        close_thread_tables() from open_and_lock_tables()
        and leave prelocked mode, thus some check in mysql_admin_table() that
        work only in prelocked/locked tables mode are no longer activated.
     @ sql/event_db_repository.h
        Function open_event_table() does not require an instance of Event_db_repository.
[21 Jul 2010 20:42] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/114101

3079 Konstantin Osipov	2010-07-22
      A pre-requisite patch for the fix for Bug#52044.
      ******
      Cleanup COM_FIELD_LIST.
      Don't call close_thread_tables() in COM_SHUTDOWN -- there
      are no open tables there that can be closed (we leave
      the locked tables mode in THD destructor, and this
      close_thread_tables() won't leave it anyway).
      ******
      Make open_and_lock_tables() close thread table in case it fails.
      Remove the calls to close_thread_tables that are now unnecessary.
      ******
      Remove the release of metadata locks
      from close_thread_tables().
      ******
      Simplify the back off condition.
      ******
      Move statement commit outside 
      close_thread_tables().
      ******
      Streamline metadata lock handling in LOCK TABLES 
      implementation.
      Add asserts.
     @ mysql-test/r/view.result
        A harmless change in CHECK TABLE <view> status for a broken view.
        If previously a failure to prelock all functions used in a view 
        would leave the connection in LTM_PRELOCKED mode, now we call
        close_thread_tables() from open_and_lock_tables()
        and leave prelocked mode, thus some check in mysql_admin_table() that
        work only in prelocked/locked tables mode are no longer activated.
     @ sql/event_db_repository.h
        Function open_event_table() does not require an instance of Event_db_repository.
[22 Jul 2010 14:03] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/114145

3082 Konstantin Osipov	2010-07-22
      A pre-requisite patch for the fix for Bug#52044.
      This patch also fixes Bug#55452 "SET PASSWORD is
      replicated twice in RBR mode"
      
      Cleanup COM_FIELD_LIST.
      Don't call close_thread_tables() in COM_SHUTDOWN -- there
      are no open tables there that can be closed (we leave
      the locked tables mode in THD destructor, and this
      close_thread_tables() won't leave it anyway).
      
      Make open_and_lock_tables() and open_and_lock_tables_derived()
      call close_thread_tables() upon failure.
      Remove the calls to close_thread_tables that are now unnecessary.
      
      Remove the release of metadata locks
      from close_thread_tables().
      
      Simplify the back off condition in Open_table_context.
      
      Move statement commit outside 
      close_thread_tables().
      
      Streamline metadata lock handling in LOCK TABLES 
      implementation.
      
      Add asserts to ensure correct life cycle of 
      statement transaction in a session.
     @ mysql-test/r/view.result
        A harmless change in CHECK TABLE <view> status for a broken view.
        If previously a failure to prelock all functions used in a view 
        would leave the connection in LTM_PRELOCKED mode, now we call
        close_thread_tables() from open_and_lock_tables()
        and leave prelocked mode, thus some check in mysql_admin_table() that
        works only in prelocked/locked tables mode is no longer activated.
     @ mysql-test/suite/rpl/r/rpl_row_implicit_commit_binlog.result
        Fixed Bug#55452 "SET PASSWORD is replicated twice in
        RBR mode": extra binlog events are gone from the
        binary log.
     @ sql/event_data_objects.cc
        Simplify code in Event_job_data::execute().
        Move sp_head memory management to lex_end().
     @ sql/event_db_repository.cc
        Move the release of metadata locks outside
        close_thread_tables().
        Make sure we call close_thread_tables() when
        open_and_lock_tables() fails and remove extra
        code from the events data dictionary.
        Use close_mysql_tables(), a new internal
        function to properly close mysql.* tables
        in the data dictionary.
        Contract Event_db_repository::drop_events_by_field,
        drop_schema_events into one function.
        When dropping all events in a schema,
        make sure we don't mistakenly release all
        locks acquired by DROP DATABASE. These
        include locks in the database name
        and the global shared metadata lock.
     @ sql/event_db_repository.h
        Function open_event_table() does not require an instance 
        of Event_db_repository.
     @ sql/events.cc
        Use close_mysql_tables() instead of close_thread_tables()
        to bootstrap events, since the latter no longer
        releases metadata locks.
     @ sql/ha_ndbcluster.cc
        - mysql_rm_table_part2 no longer releases
        acquired metadata locks. Do it in the caller.
     @ sql/ha_ndbcluster_binlog.cc
        Deploy the new protocol for closing thread
        tables in run_query() and ndb_binlog_index
        code.
     @ sql/handler.cc
        Assert that we never call ha_commit_trans/
        ha_rollback_trans in sub-statement, which
        is now the case.
     @ sql/handler.h
        Add an accessor to check whether THD_TRANS object
        is empty (has no transaction started).
     @ sql/log.cc
        Update a comment.
     @ sql/log_event.cc
        Since now we commit/rollback statement transaction in 
        mysql_execute_command(), we need a mechanism to communicate
        from Query_log_event::do_apply_event() to mysql_execute_command()
        that the statement transaction should be rolled back, not committed.
        Ideally it would be a virtual method of THD. I hesitate
        to make THD a virtual base class in this already large patch.
        Use a thd->variables.option_bits for now.
        
        Remove a call to close_thread_tables() from the slave IO
        thread. It doesn't open any tables, and the protocol
        for closing thread tables is more complicated now.
        
        Make sure we properly close thread tables, however, 
        in Load_data_log_event, which doesn't
        follow the standard server execution procedure
        with mysql_execute_command().
        @todo: this piece should use Server_runnable
        framework instead.
        Remove an unnecessary call to mysql_unlock_tables().
     @ sql/rpl_rli.cc
        Update Relay_log_info::slave_close_thread_tables()
        to follow the new close protocol.
     @ sql/set_var.cc
        Remove an unused header.
     @ sql/slave.cc
        Remove an unnecessary call to
        close_thread_tables().
     @ sql/sp.cc
        Remove unnecessary calls to close_thread_tables()
        from SP DDL implementation. The tables will
        be closed by the caller, in mysql_execute_command().
        When dropping all routines in a database, make sure
        to not mistakenly all metadata locks acquired
        so far, they include the scoped lock on the schema.
     @ sql/sp_head.cc
        Correct the protocol that closes thread tables
        in an SP instruction.
        Clear lex->sphead before cleaning up lex
        with lex_end to make sure that we don't
        delete the sphead twice. It's considered
        to be "cleaner" and more in line with
        future changes than calling delete lex->sphead
        in other places that cleanup the lex.
     @ sql/sp_head.h
        When destroying m_lex_keeper of an instruction,
        don't delete the sphead that all lex objects
        share. 
        @todo: don't store a reference to routine's sp_head
        instance in instruction's lex.
     @ sql/sql_acl.cc
        Don't call close_thread_tables() where the caller will
        do that for us.
        Fix Bug#55452 "SET PASSWORD is replicated twice in RBR 
        mode" by disabling RBR replication in change_password()
        function.
        Use close_mysql_tables() in bootstrap and ACL reload
        code to make sure we release all metadata locks.
     @ sql/sql_base.cc
        This is the main part of the patch:
        - remove manipulation with thd->transaction
        and thd->mdl_context from close_thread_tables().
        Now this function is only responsible for closing
        tables, nothing else.
        This is necessary to be able to easily use
        close_thread_tables() in procedures, that
        involve multiple open/close tables, which all
        need to be protected continuously by metadata
        locks.
        Add asserts ensuring that TABLE object
        is only used when is protected by a metadata lock.
        Simplify the back off condition of Open_table_context,
        we no longer need to look at the autocommit mode.
        Make open_and_lock_tables() and open_normal_and_derived_tables()
        close thread tables and release metadata locks acquired so-far 
        upon failure. This simplifies their usage.
        Implement close_mysql_tables().
     @ sql/sql_base.h
        Add declaration for close_mysql_tables().
     @ sql/sql_do.cc
        Do nothing in DO if inside a substatement
        (the assert moved out of trans_rollback_stmt).
     @ sql/sql_handler.cc
        Add comments.
     @ sql/sql_insert.cc
        Remove dead code. 
        Release metadata locks explicitly at the
        end of the delayed insert thread.
     @ sql/sql_lex.cc
        Add destruction of lex->sphead to lex_end(),
        lex "reset" method called at the end of each statement.
     @ sql/sql_parse.cc
        Move close_thread_tables() and other related
        cleanups to mysql_execute_command()
        from dispatch_command(). This has become
        possible after the fix for Bug#37521.
        Mark federated SERVER statements as DDL.
        
        Next step: make sure that we don't store
        eof packet in the query cache, and move
        the query cache code outside mysql_parse.
        
        Brush up the code of COM_FIELD_LIST.
        Remove unnecessary calls to close_thread_tables().
        
        When killing a query, don't report "OK"
        if it was a suicide.
     @ sql/sql_parse.h
        Remove declaration of a function that is now static.
     @ sql/sql_partition.cc
        Remove anunnecessary call to close_thread_tables().
     @ sql/sql_plugin.cc
        open_and_lock_tables() will clean up
        after itself after a failure.
        Move close_thread_tables() above
        end: label, and replace with close_mysql_tables(),
        which will also release the metadata lock
        on mysql.plugin.
     @ sql/sql_prepare.cc
        Now that we no longer release locks in close_thread_tables()
        statement prepare code has become more straightforward.
        Remove the now redundant check for thd->killed() (used
        only by the backup project) from Execute_server_runnable.
        Reorder code to take into account that now mysql_execute_command()
        performs lex->unit.cleanup() and close_thread_tables().
     @ sql/sql_priv.h
        Add a new option to server options to interact
        between the slave SQL thread and execution
        framework (hack). @todo: use a virtual
        method of class THD instead.
     @ sql/sql_servers.cc
        Due to Bug 25705 replication of 
        DROP/CREATE/ALTER SERVER is broken.
        Make sure at least we do not attempt to 
        replicate these statements using RBR,
        as this violates the assert in close_mysql_tables().
     @ sql/sql_table.cc
        Do not release metadata locks in mysql_rm_table_part2,
        this is done by the caller.
        Do not call close_thread_tables() in mysql_create_table(),
        this is done by the caller. 
        Fix a bug in DROP TABLE under LOCK TABLES when,
        upon error in wait_while_table_is_used() we would mistakenly
        release the metadata lock on a non-dropped table.
        Explicitly release metadata locks when doing an implicit
        commit.
     @ sql/sql_trigger.cc
        Now that we delete lex->sphead in lex_end(),
        zero the trigger's sphead in lex after loading
        the trigger, to avoid double deletion.
     @ sql/sql_udf.cc
        Use close_mysql_tables() instead of close_thread_tables().
     @ sql/transaction.cc
        Add asserts.
     @ sql/tztime.cc
        Use close_mysql_tables() rather than close_thread_tables().
[22 Jul 2010 14:41] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/114152

3082 Konstantin Osipov	2010-07-22
      A pre-requisite patch for the fix for Bug#52044.
      This patch also fixes Bug#55452 "SET PASSWORD is
      replicated twice in RBR mode".
      
      Cleanup COM_FIELD_LIST.
      Don't call close_thread_tables() in COM_SHUTDOWN -- there
      are no open tables there that can be closed (we leave
      the locked tables mode in THD destructor, and this
      close_thread_tables() won't leave it anyway).
      
      Make open_and_lock_tables() and open_and_lock_tables_derived()
      call close_thread_tables() upon failure.
      Remove the calls to close_thread_tables that are now unnecessary.
      
      Remove the release of metadata locks
      from close_thread_tables().
      
      Simplify the back off condition in Open_table_context.
      
      Move statement commit outside 
      close_thread_tables().
      
      Streamline metadata lock handling in LOCK TABLES 
      implementation.
      
      Add asserts to ensure correct life cycle of 
      statement transaction in a session.
     @ mysql-test/r/variables.result
        Update results: set @@autocommit and statement transaction/
        prelocked mode.
     @ mysql-test/r/view.result
        A harmless change in CHECK TABLE <view> status for a broken view.
        If previously a failure to prelock all functions used in a view 
        would leave the connection in LTM_PRELOCKED mode, now we call
        close_thread_tables() from open_and_lock_tables()
        and leave prelocked mode, thus some check in mysql_admin_table() that
        works only in prelocked/locked tables mode is no longer activated.
     @ mysql-test/suite/rpl/r/rpl_row_implicit_commit_binlog.result
        Fixed Bug#55452 "SET PASSWORD is replicated twice in
        RBR mode": extra binlog events are gone from the
        binary log.
     @ mysql-test/t/variables.test
        Add a test case: set autocommit and statement transaction/prelocked
        mode.
     @ sql/event_data_objects.cc
        Simplify code in Event_job_data::execute().
        Move sp_head memory management to lex_end().
     @ sql/event_db_repository.cc
        Move the release of metadata locks outside
        close_thread_tables().
        Make sure we call close_thread_tables() when
        open_and_lock_tables() fails and remove extra
        code from the events data dictionary.
        Use close_mysql_tables(), a new internal
        function to properly close mysql.* tables
        in the data dictionary.
        Contract Event_db_repository::drop_events_by_field,
        drop_schema_events into one function.
        When dropping all events in a schema,
        make sure we don't mistakenly release all
        locks acquired by DROP DATABASE. These
        include locks in the database name
        and the global shared metadata lock.
     @ sql/event_db_repository.h
        Function open_event_table() does not require an instance 
        of Event_db_repository.
     @ sql/events.cc
        Use close_mysql_tables() instead of close_thread_tables()
        to bootstrap events, since the latter no longer
        releases metadata locks.
     @ sql/ha_ndbcluster.cc
        - mysql_rm_table_part2 no longer releases
        acquired metadata locks. Do it in the caller.
     @ sql/ha_ndbcluster_binlog.cc
        Deploy the new protocol for closing thread
        tables in run_query() and ndb_binlog_index
        code.
     @ sql/handler.cc
        Assert that we never call ha_commit_trans/
        ha_rollback_trans in sub-statement, which
        is now the case.
     @ sql/handler.h
        Add an accessor to check whether THD_TRANS object
        is empty (has no transaction started).
     @ sql/log.cc
        Update a comment.
     @ sql/log_event.cc
        Since now we commit/rollback statement transaction in 
        mysql_execute_command(), we need a mechanism to communicate
        from Query_log_event::do_apply_event() to mysql_execute_command()
        that the statement transaction should be rolled back, not committed.
        Ideally it would be a virtual method of THD. I hesitate
        to make THD a virtual base class in this already large patch.
        Use a thd->variables.option_bits for now.
        
        Remove a call to close_thread_tables() from the slave IO
        thread. It doesn't open any tables, and the protocol
        for closing thread tables is more complicated now.
        
        Make sure we properly close thread tables, however, 
        in Load_data_log_event, which doesn't
        follow the standard server execution procedure
        with mysql_execute_command().
        @todo: this piece should use Server_runnable
        framework instead.
        Remove an unnecessary call to mysql_unlock_tables().
     @ sql/rpl_rli.cc
        Update Relay_log_info::slave_close_thread_tables()
        to follow the new close protocol.
     @ sql/set_var.cc
        Remove an unused header.
     @ sql/slave.cc
        Remove an unnecessary call to
        close_thread_tables().
     @ sql/sp.cc
        Remove unnecessary calls to close_thread_tables()
        from SP DDL implementation. The tables will
        be closed by the caller, in mysql_execute_command().
        When dropping all routines in a database, make sure
        to not mistakenly all metadata locks acquired
        so far, they include the scoped lock on the schema.
     @ sql/sp_head.cc
        Correct the protocol that closes thread tables
        in an SP instruction.
        Clear lex->sphead before cleaning up lex
        with lex_end to make sure that we don't
        delete the sphead twice. It's considered
        to be "cleaner" and more in line with
        future changes than calling delete lex->sphead
        in other places that cleanup the lex.
     @ sql/sp_head.h
        When destroying m_lex_keeper of an instruction,
        don't delete the sphead that all lex objects
        share. 
        @todo: don't store a reference to routine's sp_head
        instance in instruction's lex.
     @ sql/sql_acl.cc
        Don't call close_thread_tables() where the caller will
        do that for us.
        Fix Bug#55452 "SET PASSWORD is replicated twice in RBR 
        mode" by disabling RBR replication in change_password()
        function.
        Use close_mysql_tables() in bootstrap and ACL reload
        code to make sure we release all metadata locks.
     @ sql/sql_base.cc
        This is the main part of the patch:
        - remove manipulation with thd->transaction
        and thd->mdl_context from close_thread_tables().
        Now this function is only responsible for closing
        tables, nothing else.
        This is necessary to be able to easily use
        close_thread_tables() in procedures, that
        involve multiple open/close tables, which all
        need to be protected continuously by metadata
        locks.
        Add asserts ensuring that TABLE object
        is only used when is protected by a metadata lock.
        Simplify the back off condition of Open_table_context,
        we no longer need to look at the autocommit mode.
        Make open_and_lock_tables() and open_normal_and_derived_tables()
        close thread tables and release metadata locks acquired so-far 
        upon failure. This simplifies their usage.
        Implement close_mysql_tables().
     @ sql/sql_base.h
        Add declaration for close_mysql_tables().
     @ sql/sql_do.cc
        Do nothing in DO if inside a substatement
        (the assert moved out of trans_rollback_stmt).
     @ sql/sql_handler.cc
        Add comments.
     @ sql/sql_insert.cc
        Remove dead code. 
        Release metadata locks explicitly at the
        end of the delayed insert thread.
     @ sql/sql_lex.cc
        Add destruction of lex->sphead to lex_end(),
        lex "reset" method called at the end of each statement.
     @ sql/sql_parse.cc
        Move close_thread_tables() and other related
        cleanups to mysql_execute_command()
        from dispatch_command(). This has become
        possible after the fix for Bug#37521.
        Mark federated SERVER statements as DDL.
        
        Next step: make sure that we don't store
        eof packet in the query cache, and move
        the query cache code outside mysql_parse.
        
        Brush up the code of COM_FIELD_LIST.
        Remove unnecessary calls to close_thread_tables().
        
        When killing a query, don't report "OK"
        if it was a suicide.
     @ sql/sql_parse.h
        Remove declaration of a function that is now static.
     @ sql/sql_partition.cc
        Remove anunnecessary call to close_thread_tables().
     @ sql/sql_plugin.cc
        open_and_lock_tables() will clean up
        after itself after a failure.
        Move close_thread_tables() above
        end: label, and replace with close_mysql_tables(),
        which will also release the metadata lock
        on mysql.plugin.
     @ sql/sql_prepare.cc
        Now that we no longer release locks in close_thread_tables()
        statement prepare code has become more straightforward.
        Remove the now redundant check for thd->killed() (used
        only by the backup project) from Execute_server_runnable.
        Reorder code to take into account that now mysql_execute_command()
        performs lex->unit.cleanup() and close_thread_tables().
     @ sql/sql_priv.h
        Add a new option to server options to interact
        between the slave SQL thread and execution
        framework (hack). @todo: use a virtual
        method of class THD instead.
     @ sql/sql_servers.cc
        Due to Bug 25705 replication of 
        DROP/CREATE/ALTER SERVER is broken.
        Make sure at least we do not attempt to 
        replicate these statements using RBR,
        as this violates the assert in close_mysql_tables().
     @ sql/sql_table.cc
        Do not release metadata locks in mysql_rm_table_part2,
        this is done by the caller.
        Do not call close_thread_tables() in mysql_create_table(),
        this is done by the caller. 
        Fix a bug in DROP TABLE under LOCK TABLES when,
        upon error in wait_while_table_is_used() we would mistakenly
        release the metadata lock on a non-dropped table.
        Explicitly release metadata locks when doing an implicit
        commit.
     @ sql/sql_trigger.cc
        Now that we delete lex->sphead in lex_end(),
        zero the trigger's sphead in lex after loading
        the trigger, to avoid double deletion.
     @ sql/sql_udf.cc
        Use close_mysql_tables() instead of close_thread_tables().
     @ sql/sys_vars.cc
        Remove code added in scope of WL#4284 which would
        break when we perform set @@session.autocommit along
        with setting other variables and using tables or functions.
        A test case added to variables.test.
     @ sql/transaction.cc
        Add asserts.
     @ sql/tztime.cc
        Use close_mysql_tables() rather than close_thread_tables().
[26 Jul 2010 16:14] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/114363

3082 Konstantin Osipov	2010-07-26
      A pre-requisite patch for the fix for Bug#52044.
      This patch also fixes Bug#55452 "SET PASSWORD is
      replicated twice in RBR mode".
      
      Cleanup COM_FIELD_LIST.
      Don't call close_thread_tables() in COM_SHUTDOWN -- there
      are no open tables there that can be closed (we leave
      the locked tables mode in THD destructor, and this
      close_thread_tables() won't leave it anyway).
      
      Make open_and_lock_tables() and open_and_lock_tables_derived()
      call close_thread_tables() upon failure.
      Remove the calls to close_thread_tables that are now unnecessary.
      
      Remove the release of metadata locks
      from close_thread_tables().
      
      Simplify the back off condition in Open_table_context.
      
      Move statement commit outside 
      close_thread_tables().
      
      Streamline metadata lock handling in LOCK TABLES 
      implementation.
      
      Add asserts to ensure correct life cycle of 
      statement transaction in a session.
     @ mysql-test/r/variables.result
        Update results: set @@autocommit and statement transaction/
        prelocked mode.
     @ mysql-test/r/view.result
        A harmless change in CHECK TABLE <view> status for a broken view.
        If previously a failure to prelock all functions used in a view 
        would leave the connection in LTM_PRELOCKED mode, now we call
        close_thread_tables() from open_and_lock_tables()
        and leave prelocked mode, thus some check in mysql_admin_table() that
        works only in prelocked/locked tables mode is no longer activated.
     @ mysql-test/suite/rpl/r/rpl_row_implicit_commit_binlog.result
        Fixed Bug#55452 "SET PASSWORD is replicated twice in
        RBR mode": extra binlog events are gone from the
        binary log.
     @ mysql-test/t/variables.test
        Add a test case: set autocommit and statement transaction/prelocked
        mode.
     @ sql/event_data_objects.cc
        Simplify code in Event_job_data::execute().
        Move sp_head memory management to lex_end().
     @ sql/event_db_repository.cc
        Move the release of metadata locks outside
        close_thread_tables().
        Make sure we call close_thread_tables() when
        open_and_lock_tables() fails and remove extra
        code from the events data dictionary.
        Use close_mysql_tables(), a new internal
        function to properly close mysql.* tables
        in the data dictionary.
        Contract Event_db_repository::drop_events_by_field,
        drop_schema_events into one function.
        When dropping all events in a schema,
        make sure we don't mistakenly release all
        locks acquired by DROP DATABASE. These
        include locks in the database name
        and the global shared metadata lock.
     @ sql/event_db_repository.h
        Function open_event_table() does not require an instance 
        of Event_db_repository.
     @ sql/events.cc
        Use close_mysql_tables() instead of close_thread_tables()
        to bootstrap events, since the latter no longer
        releases metadata locks.
     @ sql/ha_ndbcluster.cc
        - mysql_rm_table_part2 no longer releases
        acquired metadata locks. Do it in the caller.
     @ sql/ha_ndbcluster_binlog.cc
        Deploy the new protocol for closing thread
        tables in run_query() and ndb_binlog_index
        code.
     @ sql/handler.cc
        Assert that we never call ha_commit_trans/
        ha_rollback_trans in sub-statement, which
        is now the case.
     @ sql/handler.h
        Add an accessor to check whether THD_TRANS object
        is empty (has no transaction started).
     @ sql/log.cc
        Update a comment.
     @ sql/log_event.cc
        Since now we commit/rollback statement transaction in 
        mysql_execute_command(), we need a mechanism to communicate
        from Query_log_event::do_apply_event() to mysql_execute_command()
        that the statement transaction should be rolled back, not committed.
        Ideally it would be a virtual method of THD. I hesitate
        to make THD a virtual base class in this already large patch.
        Use a thd->variables.option_bits for now.
        
        Remove a call to close_thread_tables() from the slave IO
        thread. It doesn't open any tables, and the protocol
        for closing thread tables is more complicated now.
        
        Make sure we properly close thread tables, however, 
        in Load_data_log_event, which doesn't
        follow the standard server execution procedure
        with mysql_execute_command().
        @todo: this piece should use Server_runnable
        framework instead.
        Remove an unnecessary call to mysql_unlock_tables().
     @ sql/rpl_rli.cc
        Update Relay_log_info::slave_close_thread_tables()
        to follow the new close protocol.
     @ sql/set_var.cc
        Remove an unused header.
     @ sql/slave.cc
        Remove an unnecessary call to
        close_thread_tables().
     @ sql/sp.cc
        Remove unnecessary calls to close_thread_tables()
        from SP DDL implementation. The tables will
        be closed by the caller, in mysql_execute_command().
        When dropping all routines in a database, make sure
        to not mistakenly all metadata locks acquired
        so far, they include the scoped lock on the schema.
     @ sql/sp_head.cc
        Correct the protocol that closes thread tables
        in an SP instruction.
        Clear lex->sphead before cleaning up lex
        with lex_end to make sure that we don't
        delete the sphead twice. It's considered
        to be "cleaner" and more in line with
        future changes than calling delete lex->sphead
        in other places that cleanup the lex.
     @ sql/sp_head.h
        When destroying m_lex_keeper of an instruction,
        don't delete the sphead that all lex objects
        share. 
        @todo: don't store a reference to routine's sp_head
        instance in instruction's lex.
     @ sql/sql_acl.cc
        Don't call close_thread_tables() where the caller will
        do that for us.
        Fix Bug#55452 "SET PASSWORD is replicated twice in RBR 
        mode" by disabling RBR replication in change_password()
        function.
        Use close_mysql_tables() in bootstrap and ACL reload
        code to make sure we release all metadata locks.
     @ sql/sql_base.cc
        This is the main part of the patch:
        - remove manipulation with thd->transaction
        and thd->mdl_context from close_thread_tables().
        Now this function is only responsible for closing
        tables, nothing else.
        This is necessary to be able to easily use
        close_thread_tables() in procedures, that
        involve multiple open/close tables, which all
        need to be protected continuously by metadata
        locks.
        Add asserts ensuring that TABLE object
        is only used when is protected by a metadata lock.
        Simplify the back off condition of Open_table_context,
        we no longer need to look at the autocommit mode.
        Make open_and_lock_tables() and open_normal_and_derived_tables()
        close thread tables and release metadata locks acquired so-far 
        upon failure. This simplifies their usage.
        Implement close_mysql_tables().
     @ sql/sql_base.h
        Add declaration for close_mysql_tables().
     @ sql/sql_do.cc
        Do nothing in DO if inside a substatement
        (the assert moved out of trans_rollback_stmt).
     @ sql/sql_handler.cc
        Add comments.
     @ sql/sql_insert.cc
        Remove dead code. 
        Release metadata locks explicitly at the
        end of the delayed insert thread.
     @ sql/sql_lex.cc
        Add destruction of lex->sphead to lex_end(),
        lex "reset" method called at the end of each statement.
     @ sql/sql_parse.cc
        Move close_thread_tables() and other related
        cleanups to mysql_execute_command()
        from dispatch_command(). This has become
        possible after the fix for Bug#37521.
        Mark federated SERVER statements as DDL.
        
        Next step: make sure that we don't store
        eof packet in the query cache, and move
        the query cache code outside mysql_parse.
        
        Brush up the code of COM_FIELD_LIST.
        Remove unnecessary calls to close_thread_tables().
        
        When killing a query, don't report "OK"
        if it was a suicide.
     @ sql/sql_parse.h
        Remove declaration of a function that is now static.
     @ sql/sql_partition.cc
        Remove an unnecessary call to close_thread_tables().
     @ sql/sql_plugin.cc
        open_and_lock_tables() will clean up
        after itself after a failure.
        Move close_thread_tables() above
        end: label, and replace with close_mysql_tables(),
        which will also release the metadata lock
        on mysql.plugin.
     @ sql/sql_prepare.cc
        Now that we no longer release locks in close_thread_tables()
        statement prepare code has become more straightforward.
        Remove the now redundant check for thd->killed() (used
        only by the backup project) from Execute_server_runnable.
        Reorder code to take into account that now mysql_execute_command()
        performs lex->unit.cleanup() and close_thread_tables().
     @ sql/sql_priv.h
        Add a new option to server options to interact
        between the slave SQL thread and execution
        framework (hack). @todo: use a virtual
        method of class THD instead.
     @ sql/sql_servers.cc
        Due to Bug 25705 replication of 
        DROP/CREATE/ALTER SERVER is broken.
        Make sure at least we do not attempt to 
        replicate these statements using RBR,
        as this violates the assert in close_mysql_tables().
     @ sql/sql_table.cc
        Do not release metadata locks in mysql_rm_table_part2,
        this is done by the caller.
        Do not call close_thread_tables() in mysql_create_table(),
        this is done by the caller. 
        Fix a bug in DROP TABLE under LOCK TABLES when,
        upon error in wait_while_table_is_used() we would mistakenly
        release the metadata lock on a non-dropped table.
        Explicitly release metadata locks when doing an implicit
        commit.
     @ sql/sql_trigger.cc
        Now that we delete lex->sphead in lex_end(),
        zero the trigger's sphead in lex after loading
        the trigger, to avoid double deletion.
     @ sql/sql_udf.cc
        Use close_mysql_tables() instead of close_thread_tables().
     @ sql/sys_vars.cc
        Remove code added in scope of WL#4284 which would
        break when we perform set @@session.autocommit along
        with setting other variables and using tables or functions.
        A test case added to variables.test.
     @ sql/transaction.cc
        Add asserts.
     @ sql/tztime.cc
        Use close_mysql_tables() rather than close_thread_tables().
[26 Jul 2010 18:35] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/114378

3082 Konstantin Osipov	2010-07-26
      A pre-requisite patch for the fix for Bug#52044.
      This patch also fixes Bug#55452 "SET PASSWORD is
      replicated twice in RBR mode".
      
      Cleanup COM_FIELD_LIST.
      Don't call close_thread_tables() in COM_SHUTDOWN -- there
      are no open tables there that can be closed (we leave
      the locked tables mode in THD destructor, and this
      close_thread_tables() won't leave it anyway).
      
      Make open_and_lock_tables() and open_and_lock_tables_derived()
      call close_thread_tables() upon failure.
      Remove the calls to close_thread_tables that are now unnecessary.
      
      Remove the release of metadata locks
      from close_thread_tables().
      
      Simplify the back off condition in Open_table_context.
      
      Move statement commit outside 
      close_thread_tables().
      
      Streamline metadata lock handling in LOCK TABLES 
      implementation.
      
      Add asserts to ensure correct life cycle of 
      statement transaction in a session.
     @ mysql-test/r/variables.result
        Update results: set @@autocommit and statement transaction/
        prelocked mode.
     @ mysql-test/r/view.result
        A harmless change in CHECK TABLE <view> status for a broken view.
        If previously a failure to prelock all functions used in a view 
        would leave the connection in LTM_PRELOCKED mode, now we call
        close_thread_tables() from open_and_lock_tables()
        and leave prelocked mode, thus some check in mysql_admin_table() that
        works only in prelocked/locked tables mode is no longer activated.
     @ mysql-test/suite/rpl/r/rpl_row_implicit_commit_binlog.result
        Fixed Bug#55452 "SET PASSWORD is replicated twice in
        RBR mode": extra binlog events are gone from the
        binary log.
     @ mysql-test/t/variables.test
        Add a test case: set autocommit and statement transaction/prelocked
        mode.
     @ sql/event_data_objects.cc
        Simplify code in Event_job_data::execute().
        Move sp_head memory management to lex_end().
     @ sql/event_db_repository.cc
        Move the release of metadata locks outside
        close_thread_tables().
        Make sure we call close_thread_tables() when
        open_and_lock_tables() fails and remove extra
        code from the events data dictionary.
        Use close_mysql_tables(), a new internal
        function to properly close mysql.* tables
        in the data dictionary.
        Contract Event_db_repository::drop_events_by_field,
        drop_schema_events into one function.
        When dropping all events in a schema,
        make sure we don't mistakenly release all
        locks acquired by DROP DATABASE. These
        include locks in the database name
        and the global shared metadata lock.
     @ sql/event_db_repository.h
        Function open_event_table() does not require an instance 
        of Event_db_repository.
     @ sql/events.cc
        Use close_mysql_tables() instead of close_thread_tables()
        to bootstrap events, since the latter no longer
        releases metadata locks.
     @ sql/ha_ndbcluster.cc
        - mysql_rm_table_part2 no longer releases
        acquired metadata locks. Do it in the caller.
     @ sql/ha_ndbcluster_binlog.cc
        Deploy the new protocol for closing thread
        tables in run_query() and ndb_binlog_index
        code.
     @ sql/handler.cc
        Assert that we never call ha_commit_trans/
        ha_rollback_trans in sub-statement, which
        is now the case.
     @ sql/handler.h
        Add an accessor to check whether THD_TRANS object
        is empty (has no transaction started).
     @ sql/log.cc
        Update a comment.
     @ sql/log_event.cc
        Since now we commit/rollback statement transaction in 
        mysql_execute_command(), we need a mechanism to communicate
        from Query_log_event::do_apply_event() to mysql_execute_command()
        that the statement transaction should be rolled back, not committed.
        Ideally it would be a virtual method of THD. I hesitate
        to make THD a virtual base class in this already large patch.
        Use a thd->variables.option_bits for now.
        
        Remove a call to close_thread_tables() from the slave IO
        thread. It doesn't open any tables, and the protocol
        for closing thread tables is more complicated now.
        
        Make sure we properly close thread tables, however, 
        in Load_data_log_event, which doesn't
        follow the standard server execution procedure
        with mysql_execute_command().
        @todo: this piece should use Server_runnable
        framework instead.
        Remove an unnecessary call to mysql_unlock_tables().
     @ sql/rpl_rli.cc
        Update Relay_log_info::slave_close_thread_tables()
        to follow the new close protocol.
     @ sql/set_var.cc
        Remove an unused header.
     @ sql/slave.cc
        Remove an unnecessary call to
        close_thread_tables().
     @ sql/sp.cc
        Remove unnecessary calls to close_thread_tables()
        from SP DDL implementation. The tables will
        be closed by the caller, in mysql_execute_command().
        When dropping all routines in a database, make sure
        to not mistakenly all metadata locks acquired
        so far, they include the scoped lock on the schema.
     @ sql/sp_head.cc
        Correct the protocol that closes thread tables
        in an SP instruction.
        Clear lex->sphead before cleaning up lex
        with lex_end to make sure that we don't
        delete the sphead twice. It's considered
        to be "cleaner" and more in line with
        future changes than calling delete lex->sphead
        in other places that cleanup the lex.
     @ sql/sp_head.h
        When destroying m_lex_keeper of an instruction,
        don't delete the sphead that all lex objects
        share. 
        @todo: don't store a reference to routine's sp_head
        instance in instruction's lex.
     @ sql/sql_acl.cc
        Don't call close_thread_tables() where the caller will
        do that for us.
        Fix Bug#55452 "SET PASSWORD is replicated twice in RBR 
        mode" by disabling RBR replication in change_password()
        function.
        Use close_mysql_tables() in bootstrap and ACL reload
        code to make sure we release all metadata locks.
     @ sql/sql_base.cc
        This is the main part of the patch:
        - remove manipulation with thd->transaction
        and thd->mdl_context from close_thread_tables().
        Now this function is only responsible for closing
        tables, nothing else.
        This is necessary to be able to easily use
        close_thread_tables() in procedures, that
        involve multiple open/close tables, which all
        need to be protected continuously by metadata
        locks.
        Add asserts ensuring that TABLE object
        is only used when is protected by a metadata lock.
        Simplify the back off condition of Open_table_context,
        we no longer need to look at the autocommit mode.
        Make open_and_lock_tables() and open_normal_and_derived_tables()
        close thread tables and release metadata locks acquired so-far 
        upon failure. This simplifies their usage.
        Implement close_mysql_tables().
     @ sql/sql_base.h
        Add declaration for close_mysql_tables().
     @ sql/sql_do.cc
        Do nothing in DO if inside a substatement
        (the assert moved out of trans_rollback_stmt).
     @ sql/sql_handler.cc
        Add comments.
     @ sql/sql_insert.cc
        Remove dead code. 
        Release metadata locks explicitly at the
        end of the delayed insert thread.
     @ sql/sql_lex.cc
        Add destruction of lex->sphead to lex_end(),
        lex "reset" method called at the end of each statement.
     @ sql/sql_parse.cc
        Move close_thread_tables() and other related
        cleanups to mysql_execute_command()
        from dispatch_command(). This has become
        possible after the fix for Bug#37521.
        Mark federated SERVER statements as DDL.
        
        Next step: make sure that we don't store
        eof packet in the query cache, and move
        the query cache code outside mysql_parse.
        
        Brush up the code of COM_FIELD_LIST.
        Remove unnecessary calls to close_thread_tables().
        
        When killing a query, don't report "OK"
        if it was a suicide.
     @ sql/sql_parse.h
        Remove declaration of a function that is now static.
     @ sql/sql_partition.cc
        Remove an unnecessary call to close_thread_tables().
     @ sql/sql_plugin.cc
        open_and_lock_tables() will clean up
        after itself after a failure.
        Move close_thread_tables() above
        end: label, and replace with close_mysql_tables(),
        which will also release the metadata lock
        on mysql.plugin.
     @ sql/sql_prepare.cc
        Now that we no longer release locks in close_thread_tables()
        statement prepare code has become more straightforward.
        Remove the now redundant check for thd->killed() (used
        only by the backup project) from Execute_server_runnable.
        Reorder code to take into account that now mysql_execute_command()
        performs lex->unit.cleanup() and close_thread_tables().
     @ sql/sql_priv.h
        Add a new option to server options to interact
        between the slave SQL thread and execution
        framework (hack). @todo: use a virtual
        method of class THD instead.
     @ sql/sql_servers.cc
        Due to Bug 25705 replication of 
        DROP/CREATE/ALTER SERVER is broken.
        Make sure at least we do not attempt to 
        replicate these statements using RBR,
        as this violates the assert in close_mysql_tables().
     @ sql/sql_table.cc
        Do not release metadata locks in mysql_rm_table_part2,
        this is done by the caller.
        Do not call close_thread_tables() in mysql_create_table(),
        this is done by the caller. 
        Fix a bug in DROP TABLE under LOCK TABLES when,
        upon error in wait_while_table_is_used() we would mistakenly
        release the metadata lock on a non-dropped table.
        Explicitly release metadata locks when doing an implicit
        commit.
     @ sql/sql_trigger.cc
        Now that we delete lex->sphead in lex_end(),
        zero the trigger's sphead in lex after loading
        the trigger, to avoid double deletion.
     @ sql/sql_udf.cc
        Use close_mysql_tables() instead of close_thread_tables().
     @ sql/sys_vars.cc
        Remove code added in scope of WL#4284 which would
        break when we perform set @@session.autocommit along
        with setting other variables and using tables or functions.
        A test case added to variables.test.
     @ sql/transaction.cc
        Add asserts.
     @ sql/tztime.cc
        Use close_mysql_tables() rather than close_thread_tables().
[27 Jul 2010 10:27] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/114426

3086 Konstantin Osipov	2010-07-27
      A pre-requisite patch for the fix for Bug#52044.
      This patch also fixes Bug#55452 "SET PASSWORD is
      replicated twice in RBR mode".
      
      The goal of this patch is to remove the release of 
      metadata locks from close_thread_tables().
      This is necessary to not mistakenly release
      the locks in the course of a multi-step
      operation that involves multiple close_thread_tables()
      or close_tables_for_reopen().
      
      On the same token, move statement commit outside 
      close_thread_tables().
      
      Other cleanups:
      Cleanup COM_FIELD_LIST.
      Don't call close_thread_tables() in COM_SHUTDOWN -- there
      are no open tables there that can be closed (we leave
      the locked tables mode in THD destructor, and this
      close_thread_tables() won't leave it anyway).
      
      Make open_and_lock_tables() and open_and_lock_tables_derived()
      call close_thread_tables() upon failure.
      Remove the calls to close_thread_tables() that are now
      unnecessary.
      
      Simplify the back off condition in Open_table_context.
      
      Streamline metadata lock handling in LOCK TABLES 
      implementation.
      
      Add asserts to ensure correct life cycle of 
      statement transaction in a session.
      
      Remove a piece of dead code that has also become redundant
      after the fix for Bug 37521.
     @ mysql-test/r/variables.result
        Update results: set @@autocommit and statement transaction/
        prelocked mode.
     @ mysql-test/r/view.result
        A harmless change in CHECK TABLE <view> status for a broken view.
        If previously a failure to prelock all functions used in a view 
        would leave the connection in LTM_PRELOCKED mode, now we call
        close_thread_tables() from open_and_lock_tables()
        and leave prelocked mode, thus some check in mysql_admin_table() that
        works only in prelocked/locked tables mode is no longer activated.
     @ mysql-test/suite/rpl/r/rpl_row_implicit_commit_binlog.result
        Fixed Bug#55452 "SET PASSWORD is replicated twice in
        RBR mode": extra binlog events are gone from the
        binary log.
     @ mysql-test/t/variables.test
        Add a test case: set autocommit and statement transaction/prelocked
        mode.
     @ sql/event_data_objects.cc
        Simplify code in Event_job_data::execute().
        Move sp_head memory management to lex_end().
     @ sql/event_db_repository.cc
        Move the release of metadata locks outside
        close_thread_tables().
        Make sure we call close_thread_tables() when
        open_and_lock_tables() fails and remove extra
        code from the events data dictionary.
        Use close_mysql_tables(), a new internal
        function to properly close mysql.* tables
        in the data dictionary.
        Contract Event_db_repository::drop_events_by_field,
        drop_schema_events into one function.
        When dropping all events in a schema,
        make sure we don't mistakenly release all
        locks acquired by DROP DATABASE. These
        include locks on the database name
        and the global intention exclusive
        metadata lock.
     @ sql/event_db_repository.h
        Function open_event_table() does not require an instance 
        of Event_db_repository.
     @ sql/events.cc
        Use close_mysql_tables() instead of close_thread_tables()
        to bootstrap events, since the latter no longer
        releases metadata locks.
     @ sql/ha_ndbcluster.cc
        - mysql_rm_table_part2 no longer releases
        acquired metadata locks. Do it in the caller.
     @ sql/ha_ndbcluster_binlog.cc
        Deploy the new protocol for closing thread
        tables in run_query() and ndb_binlog_index
        code.
     @ sql/handler.cc
        Assert that we never call ha_commit_trans/
        ha_rollback_trans in sub-statement, which
        is now the case.
     @ sql/handler.h
        Add an accessor to check whether THD_TRANS object
        is empty (has no transaction started).
     @ sql/log.cc
        Update a comment.
     @ sql/log_event.cc
        Since now we commit/rollback statement transaction in 
        mysql_execute_command(), we need a mechanism to communicate
        from Query_log_event::do_apply_event() to mysql_execute_command()
        that the statement transaction should be rolled back, not committed.
        Ideally it would be a virtual method of THD. I hesitate
        to make THD a virtual base class in this already large patch.
        Use a thd->variables.option_bits for now.
        
        Remove a call to close_thread_tables() from the slave IO
        thread. It doesn't open any tables, and the protocol
        for closing thread tables is more complicated now.
        
        Make sure we properly close thread tables, however, 
        in Load_data_log_event, which doesn't
        follow the standard server execution procedure
        with mysql_execute_command().
        @todo: this piece should use Server_runnable
        framework instead.
        Remove an unnecessary call to mysql_unlock_tables().
     @ sql/rpl_rli.cc
        Update Relay_log_info::slave_close_thread_tables()
        to follow the new close protocol.
     @ sql/set_var.cc
        Remove an unused header.
     @ sql/slave.cc
        Remove an unnecessary call to
        close_thread_tables().
     @ sql/sp.cc
        Remove unnecessary calls to close_thread_tables()
        from SP DDL implementation. The tables will
        be closed by the caller, in mysql_execute_command().
        When dropping all routines in a database, make sure
        to not mistakenly drop all metadata locks acquired
        so far, they include the scoped lock on the schema.
     @ sql/sp_head.cc
        Correct the protocol that closes thread tables
        in an SP instruction.
        Clear lex->sphead before cleaning up lex
        with lex_end to make sure that we don't
        delete the sphead twice. It's considered
        to be "cleaner" and more in line with
        future changes than calling delete lex->sphead
        in other places that cleanup the lex.
     @ sql/sp_head.h
        When destroying m_lex_keeper of an instruction,
        don't delete the sphead that all lex objects
        share. 
        @todo: don't store a reference to routine's sp_head
        instance in instruction's lex.
     @ sql/sql_acl.cc
        Don't call close_thread_tables() where the caller will
        do that for us.
        Fix Bug#55452 "SET PASSWORD is replicated twice in RBR 
        mode" by disabling RBR replication in change_password()
        function.
        Use close_mysql_tables() in bootstrap and ACL reload
        code to make sure we release all metadata locks.
     @ sql/sql_base.cc
        This is the main part of the patch:
        - remove manipulation with thd->transaction
        and thd->mdl_context from close_thread_tables().
        Now this function is only responsible for closing
        tables, nothing else.
        This is necessary to be able to easily use
        close_thread_tables() in procedures, that
        involve multiple open/close tables, which all
        need to be protected continuously by metadata
        locks.
        Add asserts ensuring that TABLE object
        is only used when is protected by a metadata lock.
        Simplify the back off condition of Open_table_context,
        we no longer need to look at the autocommit mode.
        Make open_and_lock_tables() and open_normal_and_derived_tables()
        close thread tables and release metadata locks acquired so-far 
        upon failure. This simplifies their usage.
        Implement close_mysql_tables().
     @ sql/sql_base.h
        Add declaration for close_mysql_tables().
     @ sql/sql_class.cc
        Remove a piece of dead code that has also become redundant
        after the fix for Bug 37521.
        The code became dead when my_eof() was made a non-protocol method,
        but a method that merely modifies the diagnostics area.
        The code became redundant with the fix for Bug#37521, when 
        we started to cal close_thread_tables() before
        Protocol::end_statement().
     @ sql/sql_do.cc
        Do nothing in DO if inside a substatement
        (the assert moved out of trans_rollback_stmt).
     @ sql/sql_handler.cc
        Add comments.
     @ sql/sql_insert.cc
        Remove dead code. 
        Release metadata locks explicitly at the
        end of the delayed insert thread.
     @ sql/sql_lex.cc
        Add destruction of lex->sphead to lex_end(),
        lex "reset" method called at the end of each statement.
     @ sql/sql_parse.cc
        Move close_thread_tables() and other related
        cleanups to mysql_execute_command()
        from dispatch_command(). This has become
        possible after the fix for Bug#37521.
        Mark federated SERVER statements as DDL.
        
        Next step: make sure that we don't store
        eof packet in the query cache, and move
        the query cache code outside mysql_parse.
        
        Brush up the code of COM_FIELD_LIST.
        Remove unnecessary calls to close_thread_tables().
        
        When killing a query, don't report "OK"
        if it was a suicide.
     @ sql/sql_parse.h
        Remove declaration of a function that is now static.
     @ sql/sql_partition.cc
        Remove an unnecessary call to close_thread_tables().
     @ sql/sql_plugin.cc
        open_and_lock_tables() will clean up
        after itself after a failure.
        Move close_thread_tables() above
        end: label, and replace with close_mysql_tables(),
        which will also release the metadata lock
        on mysql.plugin.
     @ sql/sql_prepare.cc
        Now that we no longer release locks in close_thread_tables()
        statement prepare code has become more straightforward.
        Remove the now redundant check for thd->killed() (used
        only by the backup project) from Execute_server_runnable.
        Reorder code to take into account that now mysql_execute_command()
        performs lex->unit.cleanup() and close_thread_tables().
     @ sql/sql_priv.h
        Add a new option to server options to interact
        between the slave SQL thread and execution
        framework (hack). @todo: use a virtual
        method of class THD instead.
     @ sql/sql_servers.cc
        Due to Bug 25705 replication of 
        DROP/CREATE/ALTER SERVER is broken.
        Make sure at least we do not attempt to 
        replicate these statements using RBR,
        as this violates the assert in close_mysql_tables().
     @ sql/sql_table.cc
        Do not release metadata locks in mysql_rm_table_part2,
        this is done by the caller.
        Do not call close_thread_tables() in mysql_create_table(),
        this is done by the caller. 
        Fix a bug in DROP TABLE under LOCK TABLES when,
        upon error in wait_while_table_is_used() we would mistakenly
        release the metadata lock on a non-dropped table.
        Explicitly release metadata locks when doing an implicit
        commit.
     @ sql/sql_trigger.cc
        Now that we delete lex->sphead in lex_end(),
        zero the trigger's sphead in lex after loading
        the trigger, to avoid double deletion.
     @ sql/sql_udf.cc
        Use close_mysql_tables() instead of close_thread_tables().
     @ sql/sys_vars.cc
        Remove code added in scope of WL#4284 which would
        break when we perform set @@session.autocommit along
        with setting other variables and using tables or functions.
        A test case added to variables.test.
     @ sql/transaction.cc
        Add asserts.
     @ sql/tztime.cc
        Use close_mysql_tables() rather than close_thread_tables().
[27 Jul 2010 13:36] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/114450

3087 Dmitry Lenev	2010-07-27
      Fix for bug #52044 "FLUSH TABLES WITH READ LOCK and FLUSH
      TABLES <list> WITH READ LOCK are incompatible".
      
      The problem was that FLUSH TABLES <list> WITH READ LOCK
      which was issued when other connection has acquired global
      read lock using FLUSH TABLES WITH READ LOCK was blocked
      and has to wait until global read lock is released.
      
      This issue stemmed from the fact that FLUSH TABLES <list>
      WITH READ LOCK implementation has acquired X metadata locks
      on tables to be flushed. Since these locks required acquiring
      of global IX lock this statement was incompatible with global
      read lock.
      
      This patch addresses problem by using SNW metadata type of
      lock for tables to be flushed by FLUSH TABLES <list> WITH
      READ LOCK. It is OK to acquire them without global IX lock
      as long as we won't try to upgrade those locks. Since SNW
      locks allow concurrent statements using same table FLUSH
      TABLE <list> WITH READ LOCK now has to wait until old
      versions of tables to be flushed go away after acquiring
      metadata locks. Since such waiting can lead to deadlock
      MDL deadlock detector was extended to take into account
      waits for flush and resolve such deadlocks.
      
      As a bonus code in open_tables() which was responsible for
      waiting old versions of tables to go away was refactored.
      Now when we encounter old version of table in open_table()
      we don't back-off and wait for all old version to go away,
      but instead wait for this particular table to be flushed.
      Such approach supported by deadlock detection should reduce
      number of scenarios in which FLUSH TABLES aborts concurrent
      multi-statement transactions.
      
      Note that active FLUSH TABLES <list> WITH READ LOCK still
      blocks concurrent FLUSH TABLES WITH READ LOCK statement
      as the former keeps tables open and thus prevents the
      latter statement from doing flush.
     @ mysql-test/include/handler.inc
        Adjusted test case after changing status which is set
        when FLUSH TABLES waits for tables to be flushed from
        "Flushing tables" to "Waiting for table".
     @ mysql-test/r/flush.result
        Added test which checks that "flush tables <list> with
        read lock" is compatible with active "flush tables with
        read lock" but not vice-versa. This test also covers
        bug #52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES
        <list> WITH READ LOCK are incompatible".
     @ mysql-test/r/mdl_sync.result
        Added scenarios in which wait for table to be flushed
        causes deadlocks to the coverage of MDL deadlock detector.
     @ mysql-test/suite/perfschema/r/dml_setup_instruments.result
        Adjusted test results after removal of COND_refresh
        condition variable.
     @ mysql-test/suite/perfschema/r/server_init.result
        Adjusted test and its results after removal of COND_refresh
        condition variable.
     @ mysql-test/suite/perfschema/t/server_init.test
        Adjusted test and its results after removal of COND_refresh
        condition variable.
     @ mysql-test/t/flush.test
        Added test which checks that "flush tables <list> with
        read lock" is compatible with active "flush tables with
        read lock" but not vice-versa. This test also covers
        bug #52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES
        <list> WITH READ LOCK are incompatible".
     @ mysql-test/t/kill.test
        Adjusted test case after changing status which is set
        when FLUSH TABLES waits for tables to be flushed from
        "Flushing tables" to "Waiting for table".
     @ mysql-test/t/lock_multi.test
        Adjusted test case after changing status which is set
        when FLUSH TABLES waits for tables to be flushed from
        "Flushing tables" to "Waiting for table".
     @ mysql-test/t/mdl_sync.test
        Added scenarios in which wait for table to be flushed
        causes deadlocks to the coverage of MDL deadlock detector.
     @ sql/ha_ndbcluster.cc
        Adjusted code after adding one more parameter for
        close_cached_tables() call - timeout for waiting for
        table to be flushed.
     @ sql/ha_ndbcluster_binlog.cc
        Adjusted code after adding one more parameter for
        close_cached_tables() call - timeout for waiting for
        table to be flushed.
     @ sql/lock.cc
        Removed COND_refresh condition variable. See comment
        for sql_base.cc for details.
     @ sql/mdl.cc
        Now MDL deadlock detector takes into account information
        about waits for table flushes when searching for deadlock.
        To implement this change:
        - Declaration of enum_deadlock_weight and
          Deadlock_detection_visitor were moved to mdl.h header
          to make them available to the code in table.cc which
          implements deadlock detector traversal through edges
          of waiters graph representing waiting for flush.
        - Since now MDL_context may wait not only for metadata
          lock but also for table to be flushed an abstract
          Wait_for_edge class was introduced. Its descendants
          MDL_ticket and Flush_ticket incapsulate specifics
          of inspecting waiters graph when following through
          edge representing wait of particular type.
        
        We no longer require global IX metadata lock when acquiring
        SNW or SNRW locks. Such locks are needed only when metadata
        locks of these types are upgraded to X locks. This allows
        to use SNW locks in FLUSH TABLES <list> WITH READ LOCK
        implementation and keep the latter compatible with global
        read lock.
     @ sql/mdl.h
        Now MDL deadlock detector takes into account information
        about waits for table flushes when searching for deadlock.
        To implement this change:
        - Declaration of enum_deadlock_weight and
          Deadlock_detection_visitor were moved to mdl.h header
          to make them available to the code in table.cc which
          implements deadlock detector traversal through edges
          of waiters graph representing waiting for flush.
        - Since now MDL_context may wait not only for metadata
          lock but also for table to be flushed an abstract
          Wait_for_edge class was introduced. Its descendants
          MDL_ticket and Flush_ticket incapsulate specifics
          of inspecting waiters graph when following through
          edge representing wait of particular type.
        - Deadlock_detection_visitor now has m_table_shares_visited
          member which allows to support recursive locking for
          LOCK_open. This is required when deadlock detector
          inspects waiters graph which contains several edges
          representing waits for flushes or needs to come through
          the such edge more than once.
     @ sql/mysqld.cc
        Removed COND_refresh condition variable. See comment
        for sql_base.cc for details.
     @ sql/mysqld.h
        Removed COND_refresh condition variable. See comment
        for sql_base.cc for details.
     @ sql/sql_base.cc
        Changed approach to how threads are waiting for table
        to be flushed. Now thread that wants to wait for old
        table to go away subscribes for notification by adding
        Flush_ticket to table's share and waits using
        MDL_context::m_wait object. Once table gets flushed
        (i.e. all tables are closed and table share is ready
        to be destroyed) all such waiters are notified
        individually.
        Thanks to this change MDL deadlock detector can take
        such waits into account.
        
        To implement this/as result of this change:
        - tdc_wait_for_old_versions() was replaced with
          tdc_wait_for_old_version() which waits for individual
          old share to go away and which is called by open_table()
          after finding out that share is outdated. We don't
          need to perform back-off before such waiting thanks
          to the fact that deadlock detector now sees such waits.
        - As result Open_table_ctx::m_mdl_requests became
          unnecessary and was removed. We no longer allocate
          copies of MDL_request objects on MEM_ROOT when
          MYSQL_OPEN_FORCE_SHARED/SHARED_HIGH_PRIO flags are
          in effect.
        - close_cached_tables() and tdc_wait_for_old_version()
          share code which implements waiting for share to be
          flushed - the both use TABLE_SHARE::wait_until_flush()
          method. Thanks to this close_cached_tables() supports
          timeouts and has extra parameter for this.
        - Open_table_context::OT_MDL_CONFLICT enum element was
          renamed to OT_CONFLICT as it is now also used in cases
          when back-off is required to resolve deadlock caused
          by waiting for flush and not metadata lock.
        - In cases when we discover that current connection tries
          to open tables from different generation we now simply
          back-off and restart process of opening tables. To
          support this Open_table_context::OT_REOPEN_TABLES enum
          element was added.
        - COND_refresh condition variable became unnecessary and
          was removed.
        - mysql_notify_thread_having_shared_lock() no longer wakes
          up connections waiting for flush as all such connections
          can be waken up by deadlock detector if necessary.
     @ sql/sql_base.h
        - close_cached_tables() now has one more parameter -
          timeout for waiting for table to be flushed.
        - Open_table_context::OT_MDL_CONFLICT enum element was
          renamed to OT_CONFLICT as it is now also used in cases
          when back-off is required to resolve deadlock caused
          by waiting for flush and not metadata lock.
          Added new OT_REOPEN_TABLES enum element to be used in
          cases when we need to restart open tables process even
          in the middle of transaction.
        - Open_table_ctx::m_mdl_requests became unnecessary and
          was removed.
     @ sql/sql_class.h
        Added assert ensuring that we won't use LOCK_open mutex
        with THD::enter_cond(). Otherwise deadlocks can arise in
        MDL deadlock detector.
     @ sql/sql_parse.cc
        Changed FLUSH TABLES <list> WITH READ LOCK to take SNW
        metadata locks instead of X locks on tables to be flushed.
        Since we no longer require global IX lock to be taken
        when SNW locks are taken this makes this statement
        compatible with FLUSH TABLES WITH READ LOCK statement.
        Since SNW locks allow other connections to have table
        opened FLUSH TABLES <list> WITH READ LOCK now has to
        wait during open_tables() for old version to go away.
        Such waits can lead to deadlocks which will be detected
        by MDL deadlock detector which now takes waits for table
        to be flushed into account.
        
        Also adjusted code after adding one more parameter for
        close_cached_tables() call - timeout for waiting for
        table to be flushed.
     @ sql/sql_yacc.yy
        FLUSH TABLES <list> WITH READ LOCK now needs only SNW
        metadata locks on tables.
     @ sql/sys_vars.cc
        Adjusted code after adding one more parameter for
        close_cached_tables() call - timeout for waiting for
        table to be flushed.
     @ sql/table.cc
        Implemented new approach to how threads are waiting for
        table to be flushed. Now thread that wants to wait for
        old table to go away subscribes for notification by
        adding Flush_ticket to table's share and waits using
        MDL_context::m_wait object. Once table gets flushed
        (i.e. all tables are closed and table share is ready
        to be destroyed) all such waiters are notified
        individually. This change allows to make such waits
        visible inside of MDL deadlock detector.
        To do it:
        
        - Added list of waiters/Flush_tickets to TABLE_SHARE
          class.
        - Changed free_table_share() to postpone freeing of
          share memory until last waiter goes away and to
          wake up subscribed waiters.
        - Added TABLE_SHARE::wait_until_flushed() method which
          implements subscription to the list of waiters for
          table to be flushed and waiting for this event.
        
        Implemented interface which allows to expose waits for
        flushes to MDL deadlock detector:
        
        - Introduced Flush_ticket class a descendant of
          Wait_for_edge class.
        - Added TABLE_SHARE::find_deadlock() method which allows
          deadlock detector to find out what contexts are still
          using old version of table in question (i.e. to find
          out what contexts are waited for by owner of
          Flush_ticket).
     @ sql/table.h
        In order to support new strategy of waiting for table flush
        (see comment for table.cc for details) added list of
        waiters/Flush_tickets to TABLE_SHARE class.
        
        Implemented interface which allows to expose waits for
        flushes to MDL deadlock detector:
        - Introduced Flush_ticket class a descendant of
          Wait_for_edge class.
        - Added TABLE_SHARE::find_deadlock() method which allows
          deadlock detector to find out what contexts are still
          using old version of table in question (i.e. to find
          out what contexts are waited for by owner of
          Flush_ticket).
[29 Jul 2010 8:35] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/114590

3090 Konstantin Osipov	2010-07-29
      Fix a Windows failure of main.merge test introduced by
      the precursor patch for Bug#52044.
      When passing the TABLE instance for invalidation to the
      query cache, we didn't always have a valid share
      (in case of error).
      Make sure we invalidate the table using TABLE_LIST, not
      TABLE, object.
     @ sql/sql_table.cc
        Make sure we invalidate the table using TABLE_LIST, not
        TABLE, object.
[4 Aug 2010 8:07] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804080001-bny5271e65xo34ig) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (merge vers: 5.6.99-m4) (pib:18)
[4 Aug 2010 8:13] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804080001-bny5271e65xo34ig) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (merge vers: 5.6.99-m4) (pib:18)
[4 Aug 2010 8:14] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804080001-bny5271e65xo34ig) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (merge vers: 5.6.99-m4) (pib:18)
[4 Aug 2010 8:15] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804080001-bny5271e65xo34ig) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (merge vers: 5.6.99-m4) (pib:18)
[4 Aug 2010 8:16] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804080001-bny5271e65xo34ig) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (merge vers: 5.6.99-m4) (pib:18)
[4 Aug 2010 8:17] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804080001-bny5271e65xo34ig) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (merge vers: 5.6.99-m4) (pib:18)
[4 Aug 2010 8:23] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804081533-c1d3rbipo9e8rt1s) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (merge vers: 5.6.99-m4) (pib:18)
[4 Aug 2010 9:00] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@ibmvm-20100804081533-c1d3rbipo9e8rt1s) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (merge vers: 5.6.99-m4) (pib:20)
[4 Aug 2010 9:03] Bugs System
Pushed into mysql-next-mr (revid:alik@ibmvm-20100804081630-ntapn8bf9pko9vj3) (version source revid:alik@sun.com-20100731075120-qz9z8c25zum2wgmm) (pib:20)
[5 Aug 2010 11:11] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/115086

3095 Konstantin Osipov	2010-08-05
      A preliminary patch that fixes Bug#41158 "DROP TABLE holds 
      LOCK_open during unlink()". This patch is a pre-requisite for 
      the fix for Bug#52044.
[5 Aug 2010 11:50] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/115087

3095 Konstantin Osipov	2010-08-05
      A preliminary patch that fixes Bug#41158 "DROP TABLE holds 
      LOCK_open during unlink()". This patch is a pre-requisite for 
      the fix for Bug#52044.
[6 Aug 2010 10:51] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/115177

3095 Dmitry Lenev	2010-08-06
      Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and
      FLUSH TABLES <list> WITH READ LOCK are incompatible" to
      be pushed as separate patch.
      
      Replaced thread state name "Waiting for table", which was
      used by threads waiting for a metadata lock or table flush, 
      with a set of names which better reflect types of resources
      being waited for.
      
      Also replaced "Table lock" thread state name, which was used 
      by threads waiting on thr_lock.c table level lock, with more
      elaborate "Waiting for table level lock", to make it 
      more consistent with other thread state names.
      
      Updated test cases and their results according to these 
      changes.
      
      Fixed sys_vars.query_cache_wlock_invalidate_func test to not
      to wait for timeout of wait_condition.inc script.
     @ mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result
        Fixed sys_vars.query_cache_wlock_invalidate_func test to not
        to wait for timeout of wait_condition.inc script. Reverted
        changes to test which introduced timeout and replaced waiting
        condition with a more appropriate one.
     @ mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test
        Fixed sys_vars.query_cache_wlock_invalidate_func test to not
        to wait for timeout of wait_condition.inc script. Reverted
        changes to test which introduced timeout and replaced waiting
        condition with a more appropriate one.
     @ mysys/thr_lock.c
        Replaced "Table lock" thread state name, which was used by 
        threads waiting on thr_lock.c table level lock, with more
        elaborate "Waiting for table level lock", to make it 
        consistent with thread state names which are used while
        waiting for metadata locks and table flush.
     @ sql/mdl.cc
        Replaced thread state name "Waiting for table", which was
        used by threads waiting for a metadata lock or table flush, 
        with a set of names which better reflect types of resources
        being waited for. 
        
        To implement this:
        - Adjusted MDL_wait::timed_wait() to take thread state name
          as parameter.
        - Introduced method of MDL_key class which allows to get
          thread state name to be used while waiting for resource
          corresponding to the key and changed code to use it.
          Added array translating namespaces to thread state names
          as part of this change.
     @ sql/mdl.h
        To implement this:
        - Adjusted MDL_wait::timed_wait() to take thread state name
          as parameter.
        - Introduced method of MDL_key class which allows to get
          thread state name to be used while waiting for resource
          corresponding to the key and changed code to use it.
          Added array translating namespaces to thread state names
          as part of this change.
     @ sql/sql_base.cc
        Replaced thread state name "Waiting for table", which was
        used by threads waiting for table flush, with a more elaborate
        "Waiting for table flush".
[6 Aug 2010 11:30] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/115184

3095 Dmitry Lenev	2010-08-06
      Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and
      FLUSH TABLES <list> WITH READ LOCK are incompatible" to
      be pushed as separate patch.
      
      Replaced thread state name "Waiting for table", which was
      used by threads waiting for a metadata lock or table flush, 
      with a set of names which better reflect types of resources
      being waited for.
      
      Also replaced "Table lock" thread state name, which was used 
      by threads waiting on thr_lock.c table level lock, with more
      elaborate "Waiting for table level lock", to make it 
      more consistent with other thread state names.
      
      Updated test cases and their results according to these 
      changes.
      
      Fixed sys_vars.query_cache_wlock_invalidate_func test to not
      to wait for timeout of wait_condition.inc script.
     @ mysql-test/r/query_cache.result
        Added test coverage for query_cache_wlock_invalidate
        behavior for implicitly locked tables.
     @ mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result
        Fixed sys_vars.query_cache_wlock_invalidate_func test to not
        to wait for timeout of wait_condition.inc script. Reverted
        changes to test which introduced timeout and replaced waiting
        condition with a more appropriate one.
        Test coverage for query_cache_wlock_invalidate behavior for
        implicitly locked tables was added to query_cache.test.
     @ mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test
        Fixed sys_vars.query_cache_wlock_invalidate_func test to not
        to wait for timeout of wait_condition.inc script. Reverted
        changes to test which introduced timeout and replaced waiting
        condition with a more appropriate one.
        Test coverage for query_cache_wlock_invalidate behavior for
        implicitly locked tables was added to query_cache.test.
     @ mysql-test/t/query_cache.test
        Added test coverage for query_cache_wlock_invalidate
        behavior for implicitly locked tables.
     @ mysys/thr_lock.c
        Replaced "Table lock" thread state name, which was used by 
        threads waiting on thr_lock.c table level lock, with more
        elaborate "Waiting for table level lock", to make it 
        consistent with thread state names which are used while
        waiting for metadata locks and table flush.
     @ sql/mdl.cc
        Replaced thread state name "Waiting for table", which was
        used by threads waiting for a metadata lock or table flush, 
        with a set of names which better reflect types of resources
        being waited for. 
        
        To implement this:
        - Adjusted MDL_wait::timed_wait() to take thread state name
          as parameter.
        - Introduced method of MDL_key class which allows to get
          thread state name to be used while waiting for resource
          corresponding to the key and changed code to use it.
          Added array translating namespaces to thread state names
          as part of this change.
     @ sql/mdl.h
        To implement this:
        - Adjusted MDL_wait::timed_wait() to take thread state name
          as parameter.
        - Introduced method of MDL_key class which allows to get
          thread state name to be used while waiting for resource
          corresponding to the key and changed code to use it.
          Added array translating namespaces to thread state names
          as part of this change.
     @ sql/sql_base.cc
        Replaced thread state name "Waiting for table", which was
        used by threads waiting for table flush, with a more elaborate
        "Waiting for table flush".
[10 Aug 2010 21:12] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/115445

3100 Konstantin Osipov	2010-08-11
      A pre-requisite patch for the fix for Bug#52044.
      Implement a few simple asserts in my_rwlock_t locks.
     @ include/my_pthread.h
        Declare two simple assert functions.
     @ include/mysql/psi/mysql_thread.h
        Add wrappers for new assert functions.
     @ mysys/thr_rwlock.c
        Add asserts.
     @ sql/sql_base.cc
        Silence a compiler warning for the case when
        SAFE_MUTEX is not ON.
[11 Aug 2010 6:59] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/115450

3095 Konstantin Osipov	2010-08-11
      Bug#52044, review comments.
[11 Aug 2010 19:18] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/115520

3096 Konstantin Osipov	2010-08-11
      Bug#52044, review comments.
[12 Aug 2010 13:52] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/115593

3101 Konstantin Osipov	2010-08-12 [merge]
      Commit on behalf of Dmitry Lenev.
      Merge his patch for Bug#52044 into 5.5, and apply 
      review comments.
[19 Aug 2010 10:43] Dmitry Lenev
Queued into 5.5-runtime
[25 Aug 2010 9:21] Bugs System
Pushed into mysql-5.5 5.5.6-m3 (revid:alik@ibmvm-20100825092002-2yvkb3iwu43ycpnm) (version source revid:alik@ibmvm-20100825092002-2yvkb3iwu43ycpnm) (merge vers: 5.5.6-m3) (pib:20)
[30 Aug 2010 8:29] Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@sun.com-20100830082732-n2eyijnv86exc5ci) (version source revid:alik@sun.com-20100830082732-n2eyijnv86exc5ci) (merge vers: 5.6.1-m4) (pib:21)
[30 Aug 2010 8:32] Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100830082745-n6sh01wlwh3itasv) (version source revid:alik@sun.com-20100830082745-n6sh01wlwh3itasv) (pib:21)
[8 Sep 2010 2:05] Paul DuBois
Noted in 5.5.6, 5.6.1 changelogs.

FLUSH TABLES WITH READ LOCK in one session and FLUSH TABLES tbl_list 
WITH READ LOCK in another session were mutually exclusive.
[13 Oct 2010 18:05] Paul DuBois
Addition to changelog entry:

This bug fix involved several changes to the states displayed by SHOW
PROCESSLIST: 

* "Table lock" was replaced with "Waiting for table level lock".

* "Waiting for table" was replaced with "Waiting for table flush".

* New states: "Waiting for global metadata lock", "Waiting for schema
  metadata lock", "Waiting for stored function metadata lock", "Waiting for
  stored procedure metadata lock", "Waiting for table metadata lock".
[9 Nov 2010 19:47] Bugs System
Pushed into mysql-5.5 5.5.7-rc (revid:sunanda.menon@sun.com-20101109182959-otkxq8vo2dcd13la) (version source revid:sunanda.menon@sun.com-20101109182959-otkxq8vo2dcd13la) (merge vers: 5.5.7-rc) (pib:21)
[13 Nov 2010 16:26] Bugs System
Pushed into mysql-trunk 5.6.99-m5 (revid:alexander.nozdrin@oracle.com-20101113155825-czmva9kg4n31anmu) (version source revid:alexander.nozdrin@oracle.com-20101113152450-2zzcm50e7i4j35v7) (merge vers: 5.6.1-m4) (pib:21)
[13 Nov 2010 16:38] Bugs System
Pushed into mysql-next-mr (revid:alexander.nozdrin@oracle.com-20101113160336-atmtmfb3mzm4pz4i) (version source revid:alexander.nozdrin@oracle.com-20101113152540-gxro4g0v29l27f5x) (pib:21)
[16 Dec 2010 21:46] Bugs System
Pushed into mysql-trunk 5.6.1 (revid:alexander.nozdrin@oracle.com-20101216181820-7afubgk2fmuv9qsb) (version source revid:alexander.nozdrin@oracle.com-20101216173826-ze3y5h450sksotrh) (merge vers: 5.6.1) (pib:23)
[16 Dec 2010 22:32] Bugs System
Pushed into mysql-5.5 5.5.9 (revid:jonathan.perkin@oracle.com-20101216101358-fyzr1epq95a3yett) (version source revid:jonathan.perkin@oracle.com-20101216101358-fyzr1epq95a3yett) (merge vers: 5.5.9) (pib:24)
[17 Dec 2010 12:50] Bugs System
Pushed into mysql-5.5 5.5.9 (revid:georgi.kodinov@oracle.com-20101217124733-p1ivu6higouawv8l) (version source revid:jon.hauglid@oracle.com-20101216095523-uguxqyzv0aai9wkb) (merge vers: 5.5.8) (pib:24)
[17 Dec 2010 12:54] Bugs System
Pushed into mysql-trunk 5.6.1 (revid:georgi.kodinov@oracle.com-20101217125013-y8pb3az32rtbplc9) (version source revid:jon.hauglid@oracle.com-20101216100953-8cjpw04foh2kqy3g) (merge vers: 5.6.1) (pib:24)
[2 Mar 2016 15:46] Paul DuBois
Revision to changelog entry:

* "Waiting for table" and "Flushing tables" were replaced with "Waiting for
table flush".