1. 10 Dec, 2009 4 commits
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.71.1 · 5e1dfa4c
      Jon Olav Hauglid authored
      Bug#42546 Backup: RESTORE fails, thinking it finds an existing table
      
      The problem occured when a MDL locking conflict happened for a non-existent 
      table between a CREATE and a INSERT statement. The code for CREATE 
      interpreted this lock conflict to mean that the table existed, 
      which meant that the statement failed when it should not have.
      The problem could occur for CREATE TABLE, CREATE TABLE LIKE and
      ALTER TABLE RENAME.
      
      This patch fixes the problem for CREATE TABLE and CREATE TABLE LIKE.
      It is based on code backported from the mysql-6.1-fk tree written
      by Dmitry Lenev. CREATE now uses normal open_and_lock_tables() code 
      to acquire exclusive locks. This means that for the test case in the bug 
      description, CREATE will wait until INSERT completes so that it can 
      get the exclusive lock. This resolves the reported bug.
      
      The patch also prohibits CREATE TABLE and CREATE TABLE LIKE under 
      LOCK TABLES. Note that this is an incompatible change and must 
      be reflected in the documentation. Affected test cases have been
      updated.
      
      mdl_sync.test contains tests for CREATE TABLE and CREATE TABLE LIKE.
      
      Fixing the issue for ALTER TABLE RENAME is beyond the scope of this
      patch. ALTER TABLE cannot be prohibited from working under LOCK TABLES
      as this could seriously impact customers and a proper fix would require
      a significant rewrite.
      5e1dfa4c
    • Magne Mahre's avatar
      Bug #46495 Crash in reload_acl_and_cache on SIGHUP · f3bc2406
      Magne Mahre authored
            
      An assert in reload_acl_and_cache didn't account for the
      case when the function is called with a NULL thd.  A
      null thd is used whenever the function is called from the
      SIGHUP signal handler.
      
      Backported from 6.0-codebase  (revid: 2617.69.35)
      
      f3bc2406
    • Konstantin Osipov's avatar
      Merge with next-4284. · f1293672
      Konstantin Osipov authored
      f1293672
    • Konstantin Osipov's avatar
      Backport of: · f26f632b
      Konstantin Osipov authored
      ------------------------------------------------------------
      revno: 2617.68.25
      committer: Dmitry Lenev <dlenev@mysql.com>
      branch nick: mysql-next-bg-pre2-2
      timestamp: Wed 2009-09-16 18:26:50 +0400
      message:
        Follow-up for one of pre-requisite patches for fixing bug #30977
        "Concurrent statement using stored function and DROP FUNCTION
        breaks SBR".
      
        Made enum_mdl_namespace enum part of MDL_key class and removed MDL_
        prefix from the names of enum members. In order to do the latter
        changed name of PROCEDURE symbol to PROCEDURE_SYM (otherwise macro
        which was automatically generated for this symbol conflicted with
        MDL_key::PROCEDURE enum member).
      f26f632b
  2. 09 Dec, 2009 22 commits
    • Konstantin Osipov's avatar
      Backport of: · 634a8109
      Konstantin Osipov authored
      ------------------------------------------------------------
      revno: 2617.68.24
      committer: Dmitry Lenev <dlenev@mysql.com>
      branch nick: mysql-next-bg-pre2-2
      timestamp: Wed 2009-09-16 17:25:29 +0400
      message:
        Pre-requisite patch for fixing bug #30977 "Concurrent statement
        using stored function and DROP FUNCTION breaks SBR".
      
        Added MDL_request for stored routine as member to Sroutine_hash_entry
        in order to be able perform metadata locking for stored routines in
        future (Sroutine_hash_entry is an equivalent of TABLE_LIST class for
        stored routines).
      (WL#4284, follow up fixes).
      
      sql/mdl.cc:
        Introduced version of MDL_request::init() method which initializes
        lock request using pre-built MDL key.
        MDL_key::table_name/table_name_length() getters were
        renamed to reflect the fact that MDL_key objects are
        now created not only for tables.
      sql/mdl.h:
        Extended enum_mdl_namespace enum with values which correspond
        to namespaces for stored functions and triggers.
        Renamed MDL_key::table_name/table_name_length() getters
        to MDL_key::name() and name_length() correspondingly to
        reflect the fact that MDL_key objects are now created
        not only for tables.
        Added MDL_key::mdl_namespace() getter.
        Also added version of MDL_request::init() method which
        initializes lock request using pre-built MDL key.
      sql/sp.cc:
        Added MDL_request for stored routine as member to Sroutine_hash_entry.
        Changed code to use MDL_key from this request as a key for LEX::sroutines
        set. Removed separate "key" member from Sroutine_hash_entry as it became
        unnecessary.
      sql/sp.h:
        Added MDL_request for stored routine as member to Sroutine_hash_entry
        in order to be able perform metadata locking for stored routines in
        future (Sroutine_hash_entry is an equivalent of TABLE_LIST class for
        stored routines).
        Removed Sroutine_hash_entry::key member as now we can use MDL_key from
        this request as a key for LEX::sroutines set.
      sql/sp_head.cc:
        Removed sp_name::m_sroutines_key member and set_routine_type() method.
        Since key for routine in LEX::sroutines set has no longer sp_name::m_qname
        as suffix we won't save anything by creating it at sp_name construction
        time.
        Adjusted sp_name constructor used for creating temporary objects for
        lookups in SP-cache to accept MDL_key as parameter and to avoid any
        memory allocation.
        Finally, removed sp_head::m_soutines_key member for reasons similar
        to why sp_name::m_sroutines_key was removed
      sql/sp_head.h:
        Removed sp_name::m_sroutines_key member and set_routine_type() method.
        Since key for routine in LEX::sroutines set has no longer sp_name::m_qname
        as suffix we won't save anything by creating it at sp_name construction
        time.
        Adjusted sp_name constructor used for creating temporary objects for
        lookups in SP-cache to accept MDL_key as parameter and to avoid any
        memory allocation.
        Finally, removed sp_head::m_soutines_key member for reasons similar
        to why sp_name::m_sroutines_key was removed.
      sql/sql_base.cc:
        Adjusted code to the fact that we now use MDL_key from
        Sroutine_hash_entry::mdl_request as a key for LEX::sroutines set.
        MDL_key::table_name/table_name_length() getters were
        renamed to reflect the fact that MDL_key objects are
        now created not only for tables.
      sql/sql_trigger.cc:
        sp_add_used_routine() now takes MDL_key as parameter as now we use
        instance of this class as a key for LEX::sroutines set.
      634a8109
    • Konstantin Osipov's avatar
      ------------------------------------------------------------ · b9d2f55a
      Konstantin Osipov authored
      revno: 2617.68.23
      committer: Dmitry Lenev <dlenev@mysql.com>
      branch nick: mysql-next-bg-pre1
      timestamp: Wed 2009-09-16 09:34:42 +0400
      message:
        Pre-requisite patch for fixing bug #30977 "Concurrent statement
        using stored function and DROP FUNCTION breaks SBR".
      
        CREATE TABLE SELECT statements take exclusive metadata lock on table
        being created. Invariant of metadata locking subsystem states that
        such lock should be taken before taking any kind of shared locks.
        Once metadata locks on stored routines are introduced statements like
        "CREATE TABLE ... SELECT f1()" will break this invariant by taking
        shared locks on routines before exclusive lock on target table.
        To avoid this, open_tables() is reworked to process tables which are
        directly used by the statement before stored routines are processed.
      
      sql/sql_base.cc:
        Refactored open_tables() implementation to process stored routines 
        only after tables which are directly used by statement were processed.
                  
        To achieve this moved handling of routines in open_tables() out of 
        loop which iterates over tables to a new separate loop. And in its 
        turn this allowed to split handling of particular table or view to 
        an auxiliary function, which made code in open_tables() simpler and 
        more easy to understand.
      b9d2f55a
    • Konstantin Osipov's avatar
      Backport of: · e001a9f0
      Konstantin Osipov authored
      ------------------------------------------------------------
      revno: 2617.68.10
      committer: Dmitry Lenev <dlenev@mysql.com>
      branch nick: mysql-next-bg46673
      timestamp: Tue 2009-09-01 19:57:05 +0400
      message:
        Fix for bug #46673 "Deadlock between FLUSH TABLES WITH READ LOCK and DML".
      
        Deadlocks occured when one concurrently executed transactions with
        several statements modifying data and FLUSH TABLES WITH READ LOCK
        statement or SET READ_ONLY=1 statement.
      
        These deadlocks were introduced by the patch for WL 4284: "Transactional
        DDL locking"/Bug 989: "If DROP TABLE while there's an active transaction,
        wrong binlog order" which has changed FLUSH TABLES WITH READ LOCK/SET
        READ_ONLY=1 to wait for pending transactions.
        What happened was that FLUSH TABLES WITH READ LOCK blocked all further
        statements changing tables by setting global_read_lock global variable
        and has started waiting for all pending transactions to complete.
        Then one of those transactions tried to executed DML, detected that
        global_read_lock non-zero and tried to wait until global read lock will
        be released (i.e. global_read_lock becomes 0), indeed, this led to a
        deadlock.
      
        Proper solution for this problem should probably involve full integration
        of global read lock with metadata locking subsystem (which will allow to
        implement waiting for pending transactions without blocking DML in them).
        But since it requires significant changes another, short-term solution
        for the problem is implemented in this patch.
      
        Basically, this patch restores behavior of FLUSH TABLES WITH READ LOCK/
        SET READ_ONLY=1 before the patch for WL 4284/bug 989. By ensuring that
        extra references to TABLE_SHARE are not stored for active metadata locks
        it changes these statements not to wait for pending transactions.
        As result deadlock is eliminated.
        Note that this does not change the fact that active FLUSH TABLES WITH
        READ LOCK lock or SET READ_ONLY=1 prevent modifications to tables as
        they also block transaction commits.
      
      
      mysql-test/r/flush_block_commit.result:
        Adjusted test case after change in FLUSH TABLES WITH READ LOCK behavior
        - it is no longer blocked by a pending transaction.
      mysql-test/r/mdl_sync.result:
        Added test for bug #46673 "Deadlock between FLUSH TABLES WITH READ LOCK
        and DML".
      mysql-test/r/read_only_innodb.result:
        Adjusted test case after change in SET READ_ONLY behavior - it is no
        longer blocked by a pending transaction.
      mysql-test/t/flush_block_commit.test:
        Adjusted test case after change in FLUSH TABLES WITH READ LOCK behavior
        - it is no longer blocked by a pending transaction.
      mysql-test/t/mdl_sync.test:
        Added test for bug #46673 "Deadlock between FLUSH TABLES WITH READ LOCK
        and DML".
      mysql-test/t/read_only_innodb.test:
        Adjusted test case after change in SET READ_ONLY behavior - it is no
        longer blocked by a pending transaction.
      sql/sql_base.cc:
        Disable caching of pointers to TABLE_SHARE objects in MDL subsystem.
        This means that transactions holding metadata lock on the table will
        no longer have extra reference to the TABLE_SHARE (due to this lock)
        and will no longer block concurrent FLUSH TABLES/FLUSH TABLES WITH
        READ LOCK. Note that this does not change the fact that FLUSH TABLES
        WITH READ LOCK prevents concurrent transactions from modifying data
        as it also blocks all commits.
      e001a9f0
    • Konstantin Osipov's avatar
      Backport of: · 2f265740
      Konstantin Osipov authored
      ------------------------------------------------------------
      revno: 2617.68.7
      committer: Dmitry Lenev <dlenev@mysql.com>
      branch nick: mysql-next-bg46044
      timestamp: Thu 2009-08-27 10:22:17 +0400
      message:
        Fix for bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE HIGH_PRIORITY
        FOR UPDATE".
      
        Deadlock occured when during execution of query to I_S we tried to open
        a table or its .FRM in order to get information about it and had to wait
        because we have encountered exclusive metadata lock on this table held by
        a DDL operation from another connection which in its turn waited for some
        resource currently owned by connection executing this I_S query.
        For example, this might have happened if one under LOCK TABLES executed I_S
        query targeted to particular table (which was not among locked) and also
        concurrently tried to create this table using CREATE TABLE SELECT which
        had to wait for one of tables locked by the first connection.
        Another situation in which deadlock might have occured is when I_S query,
        which was executed as part of transaction, tried to get information about
        table which just has been dropped by concurrent DROP TABLES executed under
        LOCK TABLES and this DROP TABLES for its completion also had to wait
        transaction from the first connection.
      
        This problem stemmed from the fact that opening of tables/.FRMs for I_S
        filling is happening outside of connection's main MDL_context so code
        which tries to detect deadlocks due to conflicting metadata locks doesn't
        work in this case. Indeed, this led to deadlocks when during I_S filling
        we tried to wait for conflicting metadata lock to go away, while its owner
        was waiting for some resource held by connection executing I_S query.
      
        This patch solves this problem by avoiding waiting in such situation.
        Instead we skip this table and produce warning that information about
        it was omitted from I_S due to concurrent DDL operation. We still wait
        for conflicting metadata lock to go away when it is known that deadlock
        is not possible (i.e. when connection executing I_S query does not hold
        any metadata or table-level locks).
        Basically, we apply our standard deadlock avoidance technique for metadata
        locks to the process of filling of I_S tables but replace ER_LOCK_DEADLOCK
        error with a warning.
        Note that this change is supposed to be safe for 'mysqldump' since the
        only its mode which is affected by this change is --single-transaction mode
        is not safe in the presence of concurrent DDL anyway (and this fact is
        documented). Other modes are unaffected because they either use
        SHOW TABLES/SELECT * FROM I_S.TABLE_NAMES which do not take any metadata
        locks in the process of I_S table filling and thus cannot skip tables or
        execute I_S queries for tables which were previously locked by LOCK TABLES
        (or in the presence of global read lock) which excludes possibility of
        encountering conflicting metadata lock.
      
      
      mysql-test/r/mdl_sync.result:
        Added test for bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE
        HIGH_PRIORITY FOR UPDATE".
      mysql-test/t/mdl_sync.test:
        Added test for bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE
        HIGH_PRIORITY FOR UPDATE".
      sql/mysql_priv.h:
        Added a new flag for open_table() call which allows it to fail
        with an error in cases when conflicting metadata lock is discovered
        instead of waiting until this lock goes away.
      sql/share/errmsg-utf8.txt:
        Added error/warning message to be generated in cases when information
        about table is omitted from I_S since there is conflicting metadata lock
        on the table.
      sql/share/errmsg.txt:
        Added error/warning message to be generated in cases when information
        about table is omitted from I_S since there is conflicting metadata lock
        on the table.
      sql/sql_base.cc:
        Added a new flag for open_table() call which allows it to fail
        with an error in cases when conflicting metadata lock is discovered
        instead of waiting until this lock goes away.
      sql/sql_show.cc:
        When we are opening a table (or just .FRM) in order to fill I_S with
        information about this table and encounter conflicting metadata lock
        waiting for this lock to go away can lead to a deadlock in some
        situations (under LOCK TABLES, within transaction, etc.). To avoid
        these deadlocks we detect such situations and don't do waiting.
        Instead, we skip table for which we have conflicting metadata lock,
        thus omitting information about it from I_S table, and produce an
        appropriate warning.
      2f265740
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.18 · 0bd57410
      Jon Olav Hauglid authored
      Bug #42147 Concurrent DML and LOCK TABLE ... READ for InnoDB 
                 table cause warnings in errlog
      
      Concurrent execution of LOCK TABLES ... READ statement and DML statements 
      affecting the same InnoDB table on debug builds of MySQL server might lead 
      to "Found lock of type 6 that is write and read locked" warnings appearing 
      in error log.
      
      The problem is that the table-level locking code allows a thread to acquire
      TL_READ_NO_INSERT lock on a table even if there is another thread which holds 
      TL_WRITE_ALLOW_WRITE lock on the same table. At the same time, the locking
      code assumes that that such locks are incompatible (for example, see check_locks()).
      
      This doesn't lead to any problems other than warnings in error log for
      debug builds of server since for InnoDB tables TL_READ_NO_INSERT type of
      lock is only used for LOCK TABLES and for this statement InnoDB also
      performs its own table-level locking.
      
      Unfortunately, the table lock compatibility matrix cannot be updated to disallow
      TL_READ_NO_INSERT when another thread holds TL_WRITE_ALLOW_WRITE without 
      causing starvation of LOCK TABLE READ in InnoDB under high write load. 
      This patch therefore contains no code changes.
      
      The issue will be fixed later when LOCK TABLE READ has been updated
      to not use table locks. This bug will therefore be marked as 
      "To be fixed later".
      
      Code comment in thr_lock.c expanded to clarify the issue and a 
      test case based on the bug description added to innodb_mysql_lock.test.
      Note that a global suppression rule has been added to both MTR v1 and v2
      for the "Found lock of type 6 that is write and read locked" warning.
      These suppression rules must be removed once this bug is properly fixed.
      0bd57410
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.13 · f3e9b392
      Jon Olav Hauglid authored
      Introduce a counter for protection against global read lock on thread level.
      
      The functions for protection against global read lock sometimes need a local
      variable to signal when the protection is set, and hence need to be released.
      It would be better to control this behaviour via a counter on the THD struct,
      telling how many times the protection has been claimed by the current thread.
      A side-effect of the fix is that if protection is claimed twice for a thread,
      only a simple increment is required for the second claim, instead of a
      mutex-protected increment of the global variable protect_against_global_read_lock.
      
      
      sql/lock.cc:
        Count how many times that we have claimed protection against global read lock.
        Assert that we really have the protection when releasing it.
        Added comments to all functions operating on global_read_lock.
      sql/sql_class.cc:
        Added the counter variable global_read_lock_protection.
      sql/sql_class.h:
        Added the counter variable global_read_lock_protection.
      sql/sql_parse.cc:
        Replaced test on local variable need_start_waiting with test on
        thd->global_read_lock_protection.
      sql/sql_table.cc:
        Replaced test on local variable need_start_waiting with test on
        thd->global_read_lock_protection.
      sql/sql_trigger.cc:
        Inserted test on thd->global_read_lock_protection.
      f3e9b392
    • unknown's avatar
      Backport of revno: 2617.68.36 · 832ad466
      unknown authored
      ---------------------------------------------
      
      This is a patch for bug#47098 assert in MDL_context::destroy on
      HANDLER <damaged merge table> OPEN.
            
      The assert occurs in MDL_context::destroy when the connection is terminated,
      because all mdl_tickets have not been released.
      MERGE tables do not support being opened using the HANDLER ... OPEN command,
      and trying to do so will result in an error. In the event of an error, all
      tables that are opened, should be closed again. The fix for bug#45781 made
      sure that this also works for MERGE tables, which causes multiple tables to
      be opened.
      This fix extends the fix for bug#45781, by ensuring that also all locks are
      released, when MERGE tables are involved.
      
      mysql-test/r/merge.result:
        The result of the test.
      mysql-test/t/merge.test:
        Added a test based on the bug report, as well as a test of the more general
        scenario.
      sql/sql_handler.cc:
        Added code to release all the locks.
      832ad466
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.31.30 · 527813b4
      Jon Olav Hauglid authored
      Bug #21793 Missing CF_CHANGES_DATA and CF_STATUS_COMMAND for 
                 handful of commands
      
      CF_CHANGES_DATA and CF_STATUS_COMMAND flags added to the 
      commands mentioned in the bug description. With the following
      two exceptions: 
      
      1) 4 commands do not exist: 
      SQLCOM_RENAME_DB
      SQLCOM_LOAD_MASTER_DATA
      SQLCOM_LOAD_MASTER_TABLE
      SQLCOM_SHOW_COLUMN_TYPES
      
      2) All SQLCOM_SHOW_* commands already had CF_STATUS_COMMAND,
      leaving only SQLCOM_BINLOG_BASE64_EVENT.
      
      Further, check_prepared_statement() in sql_prepare.cc has been
      simplified by taking advantage of the CF_STATUS_COMMAND flag.
      
      Note that no test case has been added.
      527813b4
    • Jon Olav Hauglid's avatar
      Backport of revno: 3702 · 334eb7e0
      Jon Olav Hauglid authored
      Bug #48248 assert in MDL_ticket::upgrade_shared_lock_to_exclusive
      
      The assert would happen if REPAIR TABLE was used on a table already
      locked by LOCK TABLES READ. REPAIR mistakenly tried to upgrade the
      read-lock to exclusive, thereby triggering the assert.
      
      The cause of the problem was that REPAIR TABLE ignored errors 
      from opening and locking tables. This is by design, as REPAIR
      can be used to broken tables that cannot be opened. However,
      repair also ignored logical errors such as the inability to
      exclusivly lock a table due to conflicting LOCK TABLES.
      
      This patch fixes the problem by not ignoring errors from
      opening and locking tables if inside LOCK TABLES mode.
      In LOCK TABLES we already know that the table can be opened,
      so that the failure to open must be a logical error.
      
      Test added to repair.test.
      334eb7e0
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.76.3 · dd848dfa
      Jon Olav Hauglid authored
      Bug#47107
      
      Add missing line in previous change set.
      
      
      mysql-test/r/create.result:
        Bug#47107
        
        Add missing line in previous change set.
      dd848dfa
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.76.2 · 05a126ed
      Jon Olav Hauglid authored
      Bug #47107 assert in notify_shared_lock on incorrect CREATE TABLE , HANDLER
      
      Attempts to create a table (using CREATE TABLE, CREATE TABLE LIKE or
      CREATE TABLE SELECT statements) which already existed and was opened
      by the same connection through HANDLER statement, led to a stalled
      connection (for production builds of the server) or to the server being
      aborted due to an assertion failure (for debug builds of the server).
      
      This problem was introduced by the new implementation of a metadata
      locking subsystem and didn't affect earlier versions of the server.
      
      The cause of the problem was that the HANDLER was not closed by CREATE TABLE
      before CREATE tried to open and lock the table. Acquiring an exclusive MDL
      lock on the table to be created would therefore fail since HANDLER
      already had a shared MDL lock. This triggered an assert as the 
      HANDLER and CREATE statements came from the same thread (self-deadlock).
      
      This patch resolves the issue by closing any open HANDLERs on tables
      to be created by CREATE TABLE, similar to what is already done for 
      DROP and ALTER TABLE.
      
      Test case added to create.test.
      05a126ed
    • Jon Olav Hauglid's avatar
      Backport of revno: 3711.1.1 · d40ef57d
      Jon Olav Hauglid authored
      Bug #48725 Assert !thd->is_error() in delayed_get_table()
      
      This bug is a regression introduced by the patch for Bug #45949.
      
      If the handler thread for INSERT DELAYED was killed by e.g.
      FLUSH TABLES, the error message is copied from the handler thread
      to the connection thread. But the error was not reacted on, so the
      connection thread continued as normal, leading to an eventual assert.
      
      No test case added as it would have required sync points to work
      for handler threads. The plan is to add this in the scope of 
      Bug #48725 / Bug #48541. The patch has been tested with the 
      non-deterministic test case given in the bug description.
      d40ef57d
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.69.34 · 3d1433cf
      Jon Olav Hauglid authored
      Bug #45949 Assertion `!tables->table' in open_tables() on 
                 ALTER + INSERT DELAYED
      
      The assertion was caused by improperly closing tables when 
      INSERT DELAYED needed to reopen tables. This patch replaces
      the call to close_thread_tables with close_tables_for_reopen
      which fixes the problem.
      
      The only way I was able to trigger the reopen code path and 
      thus the assertion, was if ALTER TABLE killed the delayed
      insert thread and the delayed insert thread was able to enter
      the reopen code path before it noticed that thd->killed had
      been set. Note that in these cases reopen will always fail 
      since open_table() will check thd->killed and return. This patch
      therefore adds two more thd->killed checks to minimize the 
      chance of entering the reopen code path without hope for success.
      
      The patch also changes it so that if the delayed insert is killed
      using KILL_CONNECTION, the error message that is copied to the
      connection thread is ER_QUERY_INTERRUPTED rather than 
      ER_SERVER_SHUTDOWN. This means that if INSERT DELAYED fails, 
      the user will now see "Query execution was interrupted" rather
      than the misleading "Server shutdown in progress".
      
      No test case is supplied. This is for two reasons:
      1) Unable to reproduce the error without having the delayed insert
      thread in a killed state which means that reopen is futile and
      was not supposed to be attempted.
      2) Difficulty of using sync points in other threads than 
      the connection thread.
      The patch has been successfully tested with the RQG and the grammar
      supplied in the bug description.
      3d1433cf
    • Konstantin Osipov's avatar
      Merge. · d6aaa5fd
      Konstantin Osipov authored
      d6aaa5fd
    • Konstantin Osipov's avatar
      Backport of: · 736db89a
      Konstantin Osipov authored
      ------------------------------------------------------------
      revno: 2617.69.37
      committer: Dmitry Lenev <dlenev@mysql.com>
      branch nick: mysql-next-bg46748
      timestamp: Fri 2009-08-21 18:17:02 +0400
      message:
        Fix for bug #46748 "Assertion in MDL_context::wait_for_locks()
        on INSERT + CREATE TRIGGER".
      
        Concurrent execution of statements involving stored functions or triggers
        which were using several tables and DDL statements which affected those
        tables on debug build of server might have led to assertion failures in
        MDL_context::wait_for_locks(). Non-debug build was not affected.
      
        The problem was that during back-off which happens when open_tables()
        encounters conflicting metadata lock for one of the tables being open
        we didn't reset MDL_request::ticket value for requests which correspond
        to tables from extended prelocking set. Since these requests are part
        of of list of requests to be waited for in Open_table_context this broke
        assumption that ticket value for them is 0 in MDL_context::wait_for_locks()
        and caused assertion failure.
      
        This fix ensures that close_tables_for_reopen(), which performs this back-off
        resets MDL_request::ticket value not only for tables directly used by the
        statement but also for tables from extended prelocking set, thus satisfying
        assumption described above.
      
      
      
      mysql-test/r/mdl_sync.result:
        Added test case for bug #46748 "Assertion in MDL_context::wait_for_locks()
        on INSERT + CREATE TRIGGER".
      mysql-test/t/mdl_sync.test:
        Added test case for bug #46748 "Assertion in MDL_context::wait_for_locks()
        on INSERT + CREATE TRIGGER".
      sql/sql_base.cc:
        Since metadata lock requests for tables from extended part of prelocking
        set are also part of list of requests to be waited for in Open_table_context
        in close_tables_for_reopen() we have to reset MDL_request::ticket 
        values for them to assumptions in MDL_context::wait_for_locks().
      736db89a
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.39 · fcae9927
      Jon Olav Hauglid authored
      Bug #47249 assert in MDL_global_lock::is_lock_type_compatible
      
      This assert could be triggered if LOCK TABLES were used to lock
      both a table and a view that used the same table. The table would have
      to be first WRITE locked and then READ locked. So "LOCK TABLES v1
      WRITE, t1 READ" would eventually trigger the assert, "LOCK TABLES
      v1 READ, t1 WRITE" would not. The reason is that the ordering of locks
      in the interal representation made a difference when executing 
      FLUSH TABLE on the table.
      
      During FLUSH TABLE, a lock was upgraded to exclusive. If this lock
      was of type MDL_SHARED and not MDL_SHARED_UPGRADABLE, an internal
      counter in the MDL subsystem would get out of sync. This would happen
      if the *last* mention of the table in LOCK TABLES was a READ lock.
      
      The counter in question is the number exclusive locks (active or intention). 
      This is used to make sure a global metadata lock is only taken when the 
      counter is zero (= no conflicts). The counter is increased when a
      MDL_EXCLUSIVE or MDL_SHARED_UPGRADABLE lock is taken, but not when 
      upgrade_shared_lock_to_exclusive() is used to upgrade directly
      from MDL_SHARED to MDL_EXCLUSIVE. 
      
      This patch fixes the problem by searching for a TABLE instance locked
      with MDL_SHARED_UPGRADABLE or MDL_EXCLUSIVE before calling
      upgrade_shared_lock_to_exclusive(). The patch also adds an assert checking
      that only MDL_SHARED_UPGRADABLE locks are upgraded to exclusive.
      
      Test case added to lock_multi.test.
      fcae9927
    • Konstantin Osipov's avatar
      Backport of: · 59f82702
      Konstantin Osipov authored
      ------------------------------------------------------------
      revno: 2617.69.32
      committer: Dmitry Lenev <dlenev@mysql.com>
      branch nick: mysql-next-bg46747
      timestamp: Wed 2009-08-19 18:12:27 +0400
      message:
        Fix for bug #46747 "Crash in MDL_ticket::upgrade_shared_lock_to_exclusive
        on TRIGGER + TEMP table".
      
        Server crashed when one tried to drop trigger which had its subject
        table shadowed by a temporary table with the same name.
      
        This problem occured because in such situation DROP TRIGGER has opened
        temporary table instead of base table on which trigger was defined.
        Attempt to upgrade metadata lock on this temporary table led to crash
        (we don't acquire metadata locks for temporary tables).
      
        This fix ensures that DROP TRIGGER ignores temporary tables when
        trying to open table on which trigger to be dropped is defined.
      
      
      mysql-test/r/trigger.result:
        Added test case for bug #46747 "Crash in
        MDL_ticket::upgrade_shared_lock_to_exclusive
        on TRIGGER + TEMP table".
      mysql-test/t/trigger.test:
        Added test case for bug #46747 "Crash in
        MDL_ticket::upgrade_shared_lock_to_exclusive
        on TRIGGER + TEMP table".
      sql/sql_trigger.cc:
        Prevent DROP TRIGGER from opening temporary table which might
        shadow base table on which trigger to be dropped is defined.
      59f82702
    • Konstantin Osipov's avatar
      ---------------------------------------------------------- · c0317445
      Konstantin Osipov authored
      revno: 2617.69.33
      committer: Konstantin Osipov <kostja@sun.com>
      branch nick: mysql-next-46452
      timestamp: Wed 2009-08-19 18:39:31 +0400
      message:
        Bug#46452 "Crash in MDL, HANDLER OPEN + TRUNCATE TABLE".
        Flush open HANDLER tables before TRUNCATE, which is a DDL.
      
      
      mysql-test/r/truncate.result:
        Update results for Bug#46452.
      mysql-test/t/truncate.test:
        Add a test case for Bug#46452 "Crash in MDL, HANDLER OPEN + TRUNCATE TABLE".
      c0317445
    • Konstantin Osipov's avatar
      Backpo · cb4e624f
      Konstantin Osipov authored
      ----------------------------------------------------------
      revno: 2617.69.28
      committer: Konstantin Osipov <kostja@sun.com>
      branch nick: 5.4-azalea-bugfixing
      timestamp: Tue 2009-08-18 15:27:35 +0400
      message:
        An attempt to fix a link failure on Windows -- Sroutine_hash_entry
        is forward-declared as class.
      (Part of WL#4284).
      cb4e624f
    • Konstantin Osipov's avatar
      Backport of: · 351b912e
      Konstantin Osipov authored
      ----------------------------------------------------------
      revno: 2617.69.25
      committer: Konstantin Osipov <kostja@sun.com>
      branch nick: 5.4-42546
      timestamp: Fri 2009-08-14 23:52:00 +0400
      message:
        A cleanup in open_tables() and lock_tables():
        change return type of these functions to bool from int,
        to follow convention in the rest of the code.
      (Part of WL#4284 review fixes).
      
      sql/mysql_priv.h:
        Change return type of open_talbes() and lock_tables() from
        int to bool.
      sql/sql_base.cc:
        Change return type of open_tables() and lock_tables() from int to bool.
      sql/sql_handler.cc:
        Use bool now that open_tables() returns bool.
      351b912e
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.69.40 · 546e16eb
      Jon Olav Hauglid authored
      A pre-requisite patch for Bug#30977 "Concurrent statement using 
      stored function and DROP FUNCTION breaks SBR".
      
      This patch changes the MDL API by introducing a namespace for
      lock keys: MDL_TABLE for tables and views and MDL_PROCEDURE
      for stored procedures and functions. The latter is needed for
      the fix for Bug#30977.
      546e16eb
    • Jon Olav Hauglid's avatar
      Backport of revno: 2599.169.2 · 4235167f
      Jon Olav Hauglid authored
      Bug #42074 concurrent optimize table and 
                 alter table = Assertion failed: thd->is_error()
      
      This assertion could occur if OPTIMIZE TABLE was started on a InnoDB table
      and the table was altered to different storage engine after OPTIMIZE
      had started. This allowed OPTIMIZE to pass the initial checks for 
      storage engine support, but fail once it reached "recreate+analyze"
      if this operation was not supported by the new storage engine.
      The bug had no consequences for non-debug builds of the server.
      
      In detail, the assertion was triggered when ha_analyze() returned 
      HA_ADMIN_NOT_IMPLEMENTED. This led to a code path which included an 
      assert checking for diagnostics area contents. Since this area had 
      not been filled, the assertion was triggered. The diagnostics area 
      is in this case only used to provide more detailed information about 
      why optimize failed. The triggered code path sends this information 
      to the client and clears the diagnostic area.
      
      This patch fixed the problem by adding an error message to the diagnostic 
      area if ha_analyze() fails. This error message contains the error code
      returned by ha_analyze().
      
      Test case added to innodb_mysql_sync.test.
      4235167f
  3. 08 Dec, 2009 13 commits
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.9 · 19ff2445
      Jon Olav Hauglid authored
      Bug #43272 HANDLER SQL command does not work under LOCK TABLES
      
      HANDLER commands are now explicitly disallowed in LOCK TABLES mode.
      
      Before, HANDLER OPEN gave the misleading error message: "Table x was 
      not locked with LOCK TABLES". This patch changes HANDLER OPEN/READ/CLOSE 
      to give ER_LOCK_OR_ACTIVE_TRANSACTION "Can't execute the given command 
      because you have active locked tables or an active transaction" in
      LOCK TABLES mode.
      
      Test case added to lock.test.
      19ff2445
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.65.10 · c0b78cc4
      Jon Olav Hauglid authored
      Bug #45067 Assertion `stmt_da->is_error()' in 
                 Delayed_insert::open_and_lock_table
      
      The assert was triggered when delayed insert was killed by another 
      connection using mysql_notify_thread_having_shared_lock().
      During handling of thd->killed, thd.fatal_error() was called without
      a previous call to my_error() which triggered the assert.
      This patch allows the assert to pass if thd->killed has been set.
      c0b78cc4
    • Konstantin Osipov's avatar
      Backport of: · 30235272
      Konstantin Osipov authored
      ----------------------------------------------------------
      revno: 2617.69.24
      committer: Konstantin Osipov <kostja@sun.com>
      branch nick: 5.4-42546
      timestamp: Fri 2009-08-14 19:22:05 +0400
      message:
        A pre-requisite for a fix for Bug#42546 "Backup: RESTORE fails, thinking it
        finds an existing table"
        Back-port from WL 148 "Foreign keys" feature tree a patch
        that introduced Prelocking_strategy class -- a way to parameterize
        open_tables() behaviour, implemented by Dmitry Lenev.
      
      (Part of WL#4284).
      
      sql/sql_base.cc:
        Implement different prelocking strategies. Use an instance of
        prelocking_strategy in open_tables().
      sql/sql_class.h:
        Add declarations for class Prelocking_strategy.
      sql/sql_lex.h:
        Add a helper method to access last table of the global table list
        (lex->query_tables).
      sql/sql_parse.cc:
        Use a special prelocking strategy when locking tables for LOCK TABLES.
      sql/sql_table.cc:
        Use normal open_and_lock_tables_derived() in ALTER TABLE.
      sql/sql_yacc.yy:
        Modify the grammar to not pollute the global table list with tables
        that should not be opened.
      30235272
    • Konstantin Osipov's avatar
      Merge with next-4284. · 97d2a923
      Konstantin Osipov authored
      97d2a923
    • Konstantin Osipov's avatar
      Backport of revid 2617.69.21, 2617.69.22, 2617.29.23: · 463dcbb5
      Konstantin Osipov authored
      ----------------------------------------------------------
      revno: 2617.69.21
      committer: Konstantin Osipov <kostja@sun.com>
      branch nick: 5.4-4284-1-assert
      timestamp: Thu 2009-08-13 20:13:55 +0400
      message:
        A fix and a test case for Bug#46610 "MySQL 5.4.4: MyISAM MRG engine crash
        on auto-repair of child".
        Also fixes Bug#42862 "Crash on failed attempt to open a children of a
        merge table".
      
        MERGE engine needs to extend the global table list
        with TABLE_LIST elements for child tables,
        so that they are opened and locked.
        Previously these table list elements were allocated
        in memory of ha_myisammrg object (MERGE engine handler).
        That would lead to access to freed memory in
        recover_from_failed_open_table_attempt(), which would
        try to recover a MERGE table child (MyISAM table)
        and use for that TABLE_LIST of that child.
        But by the time recover_from_failed_open_table_attempt()
        is invoked, ha_myisammrg object that owns this
        TABLE_LIST may be destroyed, and thus TABLE_LIST
        memory freed.
      
        The fix is to ensure that TABLE_LIST elements
        that are added to the global table list (lex->query_tables)
        are always allocated in thd->mem_root, which is not
        destroyed until end of execution.
      
        If previously TABLE_LIST elements were allocated
        at ha_myisammrg::open() (i.e. when the TABLE
        object was created and added to the table cache),
        now they are allocated in ha_myisammrg::add_chidlren_list()
        (i.e. right after "open" of the merge parent in
        open_tables()).
        We still create a list of children names
        at ha_myisammrg::open() to use as a basis
        for creation of TABLE_LISTs, that allows
        to avoid reading the merge handler data
        file on every execution.
      
      
      mysql-test/r/merge_recover.result:
        Test results for Bug#46610.
      mysql-test/t/merge_recover-master.opt:
        Option file for Bug#46610 test (need a new test because
        of that option, which is not tested anywhere else).
      mysql-test/t/merge_recover.test:
        Add a test case for Bug#46610.
      sql/table.h:
        MERGE child child_def_version is now moved from TABLE_LIST
        to MERGE engine specific data structure.
      storage/myisammrg/ha_myisammrg.cc:
        Introduce an auxiliary structure to keep MERGE child name
        and definition version. A list of Mrg_child_def is created
        in ha_myisammrg::open() and reused in ha_myisammrg::add_children_list().
      463dcbb5
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.65.1 · 5ce2421b
      Jon Olav Hauglid authored
      Bug #22876 Four-way deadlock
      
      This bug was fixed as a part of Bug#989 
      "If DROP TABLE while there's an active transaction, wrong binlog order"
      A statement which would have caused circular wait will now 
      be aborted with ER_LOCK_DEADLOCK.
      
      Test case based on bug description added to innodb_mysql_lock.test.
      Note that innodb_lock_wait_timeout is set to 5 mins to 
      prevent race conditions in the test.
      5ce2421b
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.62.1 · 8da6d448
      Jon Olav Hauglid authored
      Bug #39675 rename tables on innodb tables with pending 
                 transactions causes slave data issue
      
      Bug was already fixed as part of patch for Bug#989 
      (If DROP TABLE while there's an active transaction, 
      wrong binlog order) 
      
      Test case added to rpl_innodb.test.
      8da6d448
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.56.21 · a164203f
      Jon Olav Hauglid authored
      Bug #45066 FLUSH TABLES WITH READ LOCK deadlocks against LOCK TABLE
      
      Test coverage for combinations of LOCK TABLE READ / WRITE and 
      FLUSH TABLES / FLUSH TABLES WITH READ LOCK added to lock.test.
      LOCK and FLUSH are executed sequentially from one connection.
      a164203f
    • Konstantin Osipov's avatar
      Backport of: · ce5c87a3
      Konstantin Osipov authored
      ----------------------------------------------------------
      revno: 2617.69.20
      committer: Konstantin Osipov <kostja@sun.com>
      branch nick: 5.4-4284-1-assert
      timestamp: Thu 2009-08-13 18:29:55 +0400
      message:
        WL#4284 "Transactional DDL locking"
        A review fix.
        Since WL#4284 implementation separated MDL_request and MDL_ticket,
        MDL_request becamse a utility object necessary only to get a ticket.
        Store it by-value in TABLE_LIST with the intent to merge
        MDL_request::key with table_list->table_name and table_list->db
        in future.
        Change the MDL subsystem to not require MDL_requests to
        stay around till close_thread_tables().
        Remove the list of requests from the MDL context.
        Requests for shared metadata locks acquired in open_tables()
        are only used as a list in recover_from_failed_open_table_attempt(),
        which calls mdl_context.wait_for_locks() for this list.
        To keep such list for recover_from_failed_open_table_attempt(),
        introduce a context class (Open_table_context), that collects
        all requests.
        A lot of minor cleanups and simplications that became possible
        with this change.
      
      
      sql/event_db_repository.cc:
        Remove alloc_mdl_requests(). Now MDL_request instance is a member
        of TABLE_LIST, and init_one_table() initializes it.
      sql/ha_ndbcluster_binlog.cc:
        Remove now unnecessary declaration and initialization
        of binlog_mdl_request.
      sql/lock.cc:
        No need to allocate MDL requests in lock_table_names() now.
      sql/log.cc:
        Use init_one_table() method, remove alloc_mdl_requests(),
        which is now unnecessary.
      sql/log_event.cc:
        No need to allocate mdl_request separately now.
        Use init_one_table() method.
      sql/log_event_old.cc:
        Update to the new signature of close_tables_for_reopen().
      sql/mdl.cc:
        Update try_acquire_exclusive_lock() to be more easy to use.
        Function lock_table_name_if_not_cached() has been removed.
        Make acquire_shared_lock() signature consistent with
        try_acquire_exclusive_lock() signature.
        Remove methods that are no longer used.
        Update comments.
      sql/mdl.h:
        Implement an assignment operator that doesn't
        copy MDL_key (MDL_key::operator= is private and
        should remain private).
        This is a hack to work-around assignment of TABLE_LIST
        by value in several places. Such assignments violate
        encapsulation, since only perform a shallow copy.
        In most cases these assignments are a hack on their own.
      sql/mysql_priv.h:
        Update signatures of close_thread_tables() and close_tables_for_reopen().
      sql/sp.cc:
        Allocate TABLE_LIST in thd->mem_root.
        Use init_one_table().
      sql/sp_head.cc:
        Use init_one_table().
        Remove thd->locked_tables_root, it's no longer needed.
      sql/sql_acl.cc:
        Use init_mdl_requests() and init_one_table().
      sql/sql_base.cc:
        Update to new signatures of try_acquire_shared_lock() and
        try_acquire_exclusive_lock().
        Remove lock_table_name_if_not_cached().
        Fix a bug in open_ltable() that would not return ER_LOCK_DEADLOCK
        in case of a failed lock_tables() and a multi-statement
        transaction.
        Fix a bug in open_and_lock_tables_derived() that would
        not return ER_LOCK_DEADLOCK in case of a multi-statement
        transaction and a failure of lock_tables().
        Move assignment of enum_open_table_action to a method of Open_table_context, a new class that maintains information
        for backoff actions.
        Minor rearrangements of the code.
        Remove alloc_mdl_requests() in functions that work with system
        tables: instead the patch ensures that callers always initialize
        TABLE_LIST argument.
      sql/sql_class.cc:
        THD::locked_tables_root is no more.
      sql/sql_class.h:
        THD::locked_tables_root is no more.
        Add a declaration for Open_table_context class.
      sql/sql_delete.cc:
        Update to use the simplified MDL API.
      sql/sql_handler.cc:
        TABLE_LIST::mdl_request is stored by-value now.
        Ensure that mdl_request.ticket is NULL for every request
        that is passed into MDL, to satisfy MDL asserts.
        @ sql/sql_help.cc
        Function open_system_tables_for_read() no longer initializes
        mdl_requests.
        Move TABLE_LIST::mdl_request initialization closer to
        TABLE_LIST initialization.
      sql/sql_help.cc:
        Function open_system_tables_for_read() no longer initializes
        mdl_requests.
        Move TABLE_LIST::mdl_request initialization closer to
        TABLE_LIST initialization.
      sql/sql_insert.cc:
        Remove assignment by-value of TABLE_LIST in
        TABLEOP_HOOKS. We can't carry over a granted
        MDL ticket from one table list to another.
      sql/sql_parse.cc:
        Change alloc_mdl_requests() -> init_mdl_requests().
        @todo We can remove init_mdl_requests() altogether
        in some places: all places that call add_table_to_list()
        already have mdl requests initialized.
      sql/sql_plugin.cc:
        Use init_one_table().
        THD::locked_tables_root is no more.
      sql/sql_servers.cc:
        Use init_one_table().
      sql/sql_show.cc:
        Update acquire_high_priority_shared_lock() to use
        TABLE_LIST::mdl_request rather than allocate an own.
        Fix get_trigger_table_impl() to use init_one_table(),
        check for out of memory, follow the coding style.
      sql/sql_table.cc:
        Update to work with TABLE_LIST::mdl_request by-value.
        Remove lock_table_name_if_not_cached().
        The code that used to delegate to it is quite simple and
        concise without it now.
      sql/sql_udf.cc:
        Use init_one_table().
      sql/sql_update.cc:
        Update to use the new signature of close_tables_for_reopen().
      sql/table.cc:
        Move re-setting of mdl_requests for prepared statements
        and stored procedures from close_thread_tables() to
        reinit_stmt_before_use().
        Change alloc_mdl_requests() to init_mdl_requests().
        init_mdl_requests() is a hack that can't be deleted
        until we don't have a list-aware TABLE_LIST constructor.
        Hopefully its use will be minimal
      sql/table.h:
        Change alloc_mdl_requests() to init_mdl_requests()
        TABLE_LIST::mdl_request is stored by value.
      sql/tztime.cc:
        We no longer initialize mdl requests in open_system_tables_for*()
        functions. Move this initialization closer to initialization
        of the rest of TABLE_LIST members.
      storage/myisammrg/ha_myisammrg.cc:
        Simplify mdl_request initialization.
      ce5c87a3
    • Konstantin Osipov's avatar
      Backport of: · 478e0960
      Konstantin Osipov authored
      ----------------------------------------------------------
      revno: 2617.69.2
      committer: Konstantin Osipov <kostja@sun.com>
      branch nick: 5.4-azalea-bugfixing
      timestamp: Mon 2009-08-03 19:26:04 +0400
      message:
        A fix and a test case for Bug#45035 "Altering table under LOCK TABLES
        results in "Error 1213 Deadlock found...".
      
        If a user had a table locked with LOCK TABLES
        for READ and for WRITE in the same connection, ALTER TABLE
        could fail.
      
        Root cause analysis:
      
        If a connection issues
      
        LOCK TABLE t1 write, t1 a read, t1 b read;
      
        the new LOCK TABLES code in 6.0 (part of WL 3726) will create
        the following list of TABLE_LIST objects
        (thd->locked_tables_list->m_locked_tables):
      
        {"t1" "b" tl_read_no_insert}, {"t1" "a" tl_read_no_insert},
        {"t1" "t1" tl_write }
      
        Later on, when we try to ALTER table t1, mysql_alter_table()
        closes all TABLE instances and releases its thr_lock locks,
        keeping only an exclusive metadata lock on t1.
      
        But when ALTER is finished, Locked_table_list::reopen_tables()
        tries to restore the original list of open and locked tables.
      
        Before this patch, it used to do so one by one:
        Open t1 b, get TL_READ_NO_INSERT lock,
        Open t1 a, get TL_READ_NO_INSERT lock
        Open t1, try to get TL_WRITE lock, deadlock.
      
        The cause of the deadlock is that thr_lock.c doesn't
        resolve the situation when the read list only consists
        of locks taken by the same thread, followed by this very
        thread trying to take a WRITE lock. Indeed, since
        thr_lock_multi always gets a sorted list of locks,
        WRITE locks always precede READ locks in the list
        to lock.
      
        Don't try to fix thr_lock.c deficiency, keep this
        code simple.
        Instead, try to take all thr_lock locks at once
        in ::reopen_tables().
      
      
      mysql-test/r/lock.result:
        Update results: test case for Bug#45035.
      mysql-test/t/lock.test:
        Add a test case for Bug#45035.
      sql/sql_base.cc:
        Take all thr_lock locks at once in Locked_tables_list::reopen_tables().
      sql/sql_class.h:
        Add a helper array to store tables for mysql_lock_tables()
        in reopen_tables().
      sql/sql_table.cc:
        Update unlink_all_closed_tables() to the new signature.
      478e0960
    • Konstantin Osipov's avatar
      Backport of: · 226d3e4f
      Konstantin Osipov authored
      ------------------------------------------------------------
      revno: 2617.65.6
      committer: Dmitry Lenev <dlenev@mysql.com>
      branch nick: mysql-azalea-bg39674
      timestamp: Sat 2009-07-25 00:28:43 +0400
      message:
        Fix for bug #39674 "On shutdown mdl_destroy() called before
        plugin_shutdown()".
      
        Attempt to shutdown PBXT engine plugin led to assertion failure
        caused by using already destroyed mutex in metadata locking
        subsystem.
      
        This problem stemmed from the fact that we MDL subsystem and
        table definition cache were deinitialized before plugin shutdown
        while PBXT plugin during its shutdown process accessed tables and
        therefore expected them to be in working shape.
      
        This patch solves this problem by moving deinitialization of
        these two subsystems after plugins are shut down.
      
        No test case is provided since such test case would require
        using PBXT or other plugin which accesses tables during its
        shutdown process.
      
      
      sql/mysql_priv.h:
        Introduced table_def_start_shutdown() function which informs
        table definition cache that shutdown process has been started
        so it has to keep number of TABLE and TABLE_SHARE objects minimal
        in order to reduce number of references to pluggable engines.
      sql/mysqld.cc:
        Destroy table definition cache and meta-data locking subsystem
        after shutting down plugins. This allows plugins to work with
        tables during their shutdown.
        Since table definition cache hold references to storage engine
        plugins we have to remove unused tables from it before shutting
        down plugins and keep number of these references minimal during
        the process (by immediately removing tables opened during this
        process from the table definition cache).
      sql/sql_base.cc:
        Introduced table_def_start_shutdown() function which informs
        table definition cache that shutdown process has been started
        so it has to keep number of TABLE and TABLE_SHARE objects
        minimal in order to reduce number of references to pluggable
        engines.
                This allows to smoothly shutdown such plugins without completely
                prohibiting access to tables/table definition cache while
                shutting down other plugins.
      226d3e4f
    • Konstantin Osipov's avatar
      Backport of: · a26d3f99
      Konstantin Osipov authored
      ------------------------------------------------------------
      revno: 2617.43.3
      committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
      branch nick: 40188-6.0
      timestamp: Thu 2009-05-07 13:15:54 +0200
      message:
      Sort results as the file list of the database directory is not
      sorted (MY_DONT_SORT).
      
      (This is a follow-up fix for WL#4284).
      
      mysql-test/r/drop_debug.result:
        Update test case result.
      mysql-test/t/drop_debug.test:
        Sort warnings.
      a26d3f99
    • Konstantin Osipov's avatar
      Backport of: · 356597c0
      Konstantin Osipov authored
      ------------------------------------------------------------
      revno: 2617.31.7
      committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
      branch nick: mysql-6.0-runtime
      timestamp: Wed 2009-03-25 19:22:00 -0300
      message:
      WL#4284: Transactional DDL locking
      
      Post-merge fixes for test cases.
      
      mysql-test/include/mix1.inc:
        Ignore deadlock errors due to the table being altered.
      mysql-test/r/innodb_mysql.result:
        Update test case result (WL$4284).
      mysql-test/suite/parts/r/partition_special_innodb.result:
        The INSERT and SELECT are not necessary to reproduce the
        problem as the assertion happens when the table is being
        altered.
               
        Furthermore, the INSERT and SELECT will yield a deadlock
        error as after the alter the table version is set to zero,
        which means that any metadata locks on the table must be
        relinquished, but this won't happen voluntarily in a
        multi-statement transaction (metadata locks are released
        on commit or rollback). Reported as Bug#43867.
      mysql-test/suite/parts/t/partition_special_innodb.test:
        The INSERT and SELECT are not necessary to reproduce the
        problem as the assertion happens when the table is being
        altered.
               
        Furthermore, the INSERT and SELECT will yield a deadlock
        error as after the alter the table version is set to zero,
        which means that any metadata locks on the table must be
        relinquished, but this won't happen voluntarily in a
        multi-statement transaction (metadata locks are released
        on commit or rollback). Reported as Bug#43867.
      356597c0
  4. 04 Dec, 2009 1 commit
    • Konstantin Osipov's avatar
      Backport of revno ## 2617.31.1, 2617.31.3, 2617.31.4, 2617.31.5, · a14bbee5
      Konstantin Osipov authored
      2617.31.12, 2617.31.15, 2617.31.15, 2617.31.16, 2617.43.1
      - initial changeset that introduced the fix for 
      Bug#989 and follow up fixes for all test suite failures
      introduced in the initial changeset. 
      ------------------------------------------------------------
      revno: 2617.31.1
      committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
      branch nick: 4284-6.0
      timestamp: Fri 2009-03-06 19:17:00 -0300
      message:
      Bug#989: If DROP TABLE while there's an active transaction, wrong binlog order
      WL#4284: Transactional DDL locking
      
      Currently the MySQL server does not keep metadata locks on
      schema objects for the duration of a transaction, thus failing
      to guarantee the integrity of the schema objects being used
      during the transaction and to protect then from concurrent
      DDL operations. This also poses a problem for replication as
      a DDL operation might be replicated even thought there are
      active transactions using the object being modified.
      
      The solution is to defer the release of metadata locks until
      a active transaction is either committed or rolled back. This
      prevents other statements from modifying the table for the
      entire duration of the transaction. This provides commitment
      ordering for guaranteeing serializability across multiple
      transactions.
      
      - Incompatible change:
      
      If MySQL's metadata locking system encounters a lock conflict,
      the usual schema is to use the try and back-off technique to
      avoid deadlocks -- this schema consists in releasing all locks
      and trying to acquire them all in one go.
      
      But in a transactional context this algorithm can't be utilized
      as its not possible to release locks acquired during the course
      of the transaction without breaking the transaction commitments.
      To avoid deadlocks in this case, the ER_LOCK_DEADLOCK will be
      returned if a lock conflict is encountered during a transaction.
      
      Let's consider an example:
      
      A transaction has two statements that modify table t1, then table
      t2, and then commits. The first statement of the transaction will
      acquire a shared metadata lock on table t1, and it will be kept
      utill COMMIT to ensure serializability.
      
      At the moment when the second statement attempts to acquire a
      shared metadata lock on t2, a concurrent ALTER or DROP statement
      might have locked t2 exclusively. The prescription of the current
      locking protocol is that the acquirer of the shared lock backs off
      -- gives up all his current locks and retries. This implies that
      the entire multi-statement transaction has to be rolled back.
      
      - Incompatible change:
      
      FLUSH commands such as FLUSH PRIVILEGES and FLUSH TABLES WITH READ
      LOCK won't cause locked tables to be implicitly unlocked anymore.
      
      
      mysql-test/extra/binlog_tests/drop_table.test:
        Add test case for Bug#989.
      mysql-test/extra/binlog_tests/mix_innodb_myisam_binlog.test:
        Fix test case to reflect the fact that transactions now hold
        metadata locks for the duration of a transaction.
      mysql-test/include/mix1.inc:
        Fix test case to reflect the fact that transactions now hold
        metadata locks for the duration of a transaction.
      mysql-test/include/mix2.inc:
        Fix test case to reflect the fact that transactions now hold
        metadata locks for the duration of a transaction.
      mysql-test/r/flush_block_commit.result:
        Update test case result (WL#4284).
      mysql-test/r/flush_block_commit_notembedded.result:
        Update test case result (WL#4284).
      mysql-test/r/innodb.result:
        Update test case result (WL#4284).
      mysql-test/r/innodb_mysql.result:
        Update test case result (WL#4284).
      mysql-test/r/lock.result:
        Add test case result for an effect of WL#4284/Bug#989
        (all locks should be released when a connection terminates).
      mysql-test/r/mix2_myisam.result:
        Update test case result (effects of WL#4284/Bug#989).
      mysql-test/r/not_embedded_server.result:
        Update test case result (effects of WL#4284/Bug#989).
        Add a test case for interaction of WL#4284 and FLUSH PRIVILEGES.
      mysql-test/r/partition_innodb_semi_consistent.result:
        Update test case result (effects of WL#4284/Bug#989).
      mysql-test/r/partition_sync.result:
        Temporarily disable the test case for Bug#43867,
        which will be fixed by a subsequent backport.
      mysql-test/r/ps.result:
        Add a test case for effect of PREPARE on transactional
        locks: we take a savepoint at beginning of PREAPRE
        and release it at the end. Thus PREPARE does not 
        accumulate metadata locks (Bug#989/WL#4284).
      mysql-test/r/read_only_innodb.result:
        Update test case result (effects of WL#4284/Bug#989).
      mysql-test/suite/binlog/r/binlog_row_drop_tbl.result:
        Add a test case result (WL#4284/Bug#989).
      mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result:
        Update test case result (effects of WL#4284/Bug#989).
      mysql-test/suite/binlog/r/binlog_stm_drop_tbl.result:
        Add a test case result (WL#4284/Bug#989).
      mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result:
        Update test case result (effects of WL#4284/Bug#989).
      mysql-test/suite/binlog/r/binlog_unsafe.result:
        A side effect of Bug#989 -- slightly different table map ids.
      mysql-test/suite/binlog/t/binlog_row_drop_tbl.test:
        Add a test case for WL#4284/Bug#989.
      mysql-test/suite/binlog/t/binlog_stm_drop_tbl.test:
        Add a test case for WL#4284/Bug#989.
      mysql-test/suite/binlog/t/binlog_stm_row.test:
        Update to the new state name. This
        is actually a follow up to another patch for WL#4284, 
        that changes Locked thread state to Table lock.
      mysql-test/suite/ndb/r/ndb_index_ordered.result:
        Remove result for disabled part of the test case.
      mysql-test/suite/ndb/t/disabled.def:
        Temporarily disable a test case (Bug#45621).
      mysql-test/suite/ndb/t/ndb_index_ordered.test:
        Disable a part of a test case (needs update to
        reflect semantics of Bug#989).
      mysql-test/suite/rpl/t/disabled.def:
        Disable tests made meaningless by transactional metadata
        locking.
      mysql-test/suite/sys_vars/r/autocommit_func.result:
        Add a commit (Bug#989).
      mysql-test/suite/sys_vars/t/autocommit_func.test:
        Add a commit (Bug#989).
      mysql-test/t/flush_block_commit.test:
        Fix test case to reflect the fact that transactions now hold
        metadata locks for the duration of a transaction.
      mysql-test/t/flush_block_commit_notembedded.test:
        Fix test case to reflect the fact that transactions now hold
        metadata locks for the duration of a transaction.
        Add a test case for transaction-scope locks and the global
        read lock (Bug#989/WL#4284).
      mysql-test/t/innodb.test:
        Fix test case to reflect the fact that transactions now hold
        metadata locks for the duration of a transaction
        (effects of Bug#989/WL#4284).
      mysql-test/t/lock.test:
        Add a test case for Bug#989/WL#4284.
      mysql-test/t/not_embedded_server.test:
        Add a test case for Bug#989/WL#4284.
      mysql-test/t/partition_innodb_semi_consistent.test:
        Replace TRUNCATE with DELETE, to not issue
        an implicit commit of a transaction, and not depend
        on metadata locks.
      mysql-test/t/partition_sync.test:
        Temporarily disable the test case for Bug#43867,
        which needs a fix to be backported from 6.0.
      mysql-test/t/ps.test:
        Add a test case for semantics of PREPARE and transaction-scope
        locks: metadata locks on tables used in PREPARE are enclosed into a
        temporary savepoint, taken at the beginning of PREPARE,
        and released at the end. Thus PREPARE does not effect
        what locks a transaction owns.
      mysql-test/t/read_only_innodb.test:
        Fix test case to reflect the fact that transactions now hold
        metadata locks for the duration of a transaction 
        (Bug#989/WL#4284).
        
        Wait for the read_only statement to actually flush tables before
        sending other concurrent statements that depend on its state.
      mysql-test/t/xa.test:
        Fix test case to reflect the fact that transactions now hold
        metadata locks for the duration of a transaction 
        (Bug#989/WL#4284).
      sql/ha_ndbcluster_binlog.cc:
        Backport bits of changes of ha_ndbcluster_binlog.cc
        from 6.0, to fix the failing binlog test suite with
        WL#4284. WL#4284 implementation does not work
        with 5.1 implementation of ndbcluster binlog index.
      sql/log_event.cc:
        Release metadata locks after issuing a commit.
      sql/mdl.cc:
        Style changes (WL#4284).
      sql/mysql_priv.h:
        Rename parameter to match the name used in the definition (WL#4284).
      sql/rpl_injector.cc:
        Release metadata locks on commit (WL#4284).
      sql/rpl_rli.cc:
        Remove assert made meaningless, metadata locks are released
        at the end of the transaction.
      sql/set_var.cc:
        Close tables and release locks if autocommit mode is set.
      sql/slave.cc:
        Release metadata locks after a rollback.
      sql/sql_acl.cc:
        Don't implicitly unlock locked tables. Issue a implicit commit
        at the end and unlock tables.
      sql/sql_base.cc:
        Defer the release of metadata locks when closing tables
        if not required to.
        Issue a deadlock error if the locking protocol requires
        that a transaction re-acquire its locks.
        
        Release metadata locks when closing tables for reopen.
      sql/sql_class.cc:
        Release metadata locks if the thread is killed.
      sql/sql_parse.cc:
        Release metadata locks after implicitly committing a active
        transaction, or after explicit commits or rollbacks.
      sql/sql_plugin.cc:
        
        Allocate MDL request on the stack as the use of the table
        is contained within the function. It will be removed from
        the context once close_thread_tables is called at the end
        of the function.
      sql/sql_prepare.cc:
        The problem is that the prepare phase of the CREATE TABLE
        statement takes a exclusive metadata lock lock and this can
        cause a self-deadlock the thread already holds a shared lock
        on the table being that should be created.
        
        The solution is to make the prepare phase take a shared
        metadata lock when preparing a CREATE TABLE statement. The
        execution of the statement will still acquire a exclusive
        lock, but won't cause any problem as it issues a implicit
        commit.
        
        After some discussions with stakeholders it has been decided that
        metadata locks acquired during a PREPARE statement must be released
        once the statement is prepared even if it is prepared within a multi
        statement transaction.
      sql/sql_servers.cc:
        Don't implicitly unlock locked tables. Issue a implicit commit
        at the end and unlock tables.
      sql/sql_table.cc:
        Close table and release metadata locks after a admin operation.
      sql/table.h:
        The problem is that the prepare phase of the CREATE TABLE
        statement takes a exclusive metadata lock lock and this can
        cause a self-deadlock the thread already holds a shared lock
        on the table being that should be created.
        
        The solution is to make the prepare phase take a shared
        metadata lock when preparing a CREATE TABLE statement. The
        execution of the statement will still acquire a exclusive
        lock, but won't cause any problem as it issues a implicit
        commit.
      sql/transaction.cc:
        Release metadata locks after the implicitly committed due
        to a new transaction being started. Also, release metadata
        locks acquired after a savepoint if the transaction is rolled
        back to the save point.
        
        The problem is that in some cases transaction-long metadata locks
        could be released before the transaction was committed. This could
        happen when a active transaction was ended by a "START TRANSACTION"
        or "BEGIN" statement, in which case the metadata locks would be
        released before the actual commit of the active transaction.
        
        The solution is to defer the release of metadata locks to after the
        transaction has been implicitly committed. No test case is provided
        as the effort to provide one is too disproportional to the size of
        the fix.
      a14bbee5