1. 11 Dec, 2009 5 commits
    • Konstantin Osipov's avatar
      Backport of: · 5a4f8e21
      Konstantin Osipov authored
      ------------------------------------------------------------
       2599.161.3 Ingo Struewing      2009-07-21
       Bug#20667 - Truncate table fails for a write locked table
      
       TRUNCATE TABLE was not allowed under LOCK TABLES.
      
       The patch removes this restriction. mysql_truncate()
       does now handle that case.
      
      
      mysql-test/r/merge.result:
        Bug#20667 - Truncate table fails for a write locked table
        Updated test result.
      mysql-test/r/truncate.result:
        Bug#20667 - Truncate table fails for a write locked table
        Updated test result.
      mysql-test/r/truncate_coverage.result:
        Bug#20667 - Truncate table fails for a write locked table
        New test result.
      mysql-test/t/merge.test:
        Bug#20667 - Truncate table fails for a write locked table
        Updated test case due to now working TRUNCATE under LOCK TABLES.
        Added some SELECTs to show that child tables are truncated.
      mysql-test/t/truncate.test:
        Bug#20667 - Truncate table fails for a write locked table
        Added test cases for TRUNCATE under LOCK TABLE.
      mysql-test/t/truncate_coverage.test:
        Bug#20667 - Truncate table fails for a write locked table
        New test file. Coverage tests for TRUNCATE.
      sql/sql_delete.cc:
        Bug#20667 - Truncate table fails for a write locked table
        Added branches for thd->locked_tables_mode.
      sql/sql_parse.cc:
        Bug#20667 - Truncate table fails for a write locked table
        Deleted rejection of TRUNCATE in case of LOCK TABLES.
      5a4f8e21
    • Konstantin Osipov's avatar
      Backport of: · 3097c22a
      Konstantin Osipov authored
      -----------------------------------------------------------
      2630.28.28 Magne Mahre  2008-12-05
      Bug #38661 'all threads hang in "opening tables" or "waiting for table"
                  and cpu is at 100%'
                            
      Concurrent execution of FLUSH TABLES statement and at least two statements
      using the same table might have led to live-lock which caused all three
      connections to stall and hog 100% of CPU.
              
      tdc_wait_for_old_versions() wrongly assumed that there cannot be a share
      with an old version and no used TABLE instances and thus was failing to
      perform wait in situation when such old share was cached in MDL subsystem
      thanks to a still active metadata lock on the table. So it might have
      happened that two or more connections simultaneously executing statements
      which involve table being flushed managed to prevent each other from
      waiting in this function by keeping shared metadata lock on the table 
      constantly active (i.e. one of the statements managed to take/hold this
      lock while other statements were calling tdc_wait_for_old_versions()).
      Thus they were forcing each other to loop infinitely in open_tables() - 
      close_thread_tables_for_reopen() - tdc_wait_for_old_versions() cycle
      causing CPU hogging.
              
      This patch fixes this problem by removing this false assumption from
      tdc_wait_for_old_versions().
       
      Note that the problem is specific only for server versions >= 6.0.
              
      No test case is submitted for this test, as the test infrastructure
      hasn't got the necessary primitives to test the behaviour.  The
      manifestation is that throughput will decrease to a low level
      (possibly 0) after some time, and stay at that level. Several
      transactions will not complete. 
              
      Manual testing can be done by running the code submitted by Shane 
      Bester attached to the bug report.  If the bug persists, the 
      transaction thruput will almost immediately drop to near zero 
      (shown as the transaction count output from the test program staying 
      on a close to constant value, instead of increasing rapidly).
      3097c22a
    • Konstantin Osipov's avatar
      Partial backport of: · 42ed7740
      Konstantin Osipov authored
      -----------------------------------------------------------
      2497.392.1 Michael Widenius	2008-08-19
      Fixes for Bug #38016 Maria: trying to access freed memory when
      committing a transaction.
      Don't write out states if they haven't changed.
      
      
      sql/sql_table.cc:
        Call extra(HA_EXTRA_PREPARE_FOR_RENAME) before renaming a table.
      42ed7740
    • Konstantin Osipov's avatar
      Partial backport of: · 1a122dc2
      Konstantin Osipov authored
      ----------------------------------------------------
      2736.2.10 Michael Widenius	2008-10-22
      Fix for bug#39395 Maria: ma_extra.c:286: maria_extra: 
      Assertion `share->reopen == 1' failed
      
      
      sql/sql_base.cc:
        Race condition in wait_while_table_is_used() where a table used 
        by another connection could be forced closed, but there was no protection against the other thread re-opening the table and trying to lock it 
        again before the table was name locked by original thread.
      1a122dc2
    • Konstantin Osipov's avatar
      Merge with next-4284. · b89c882c
      Konstantin Osipov authored
      b89c882c
  2. 10 Dec, 2009 17 commits
    • Magne Mahre's avatar
      Bug#46374 crash, INSERT INTO t1 uses function, function modifies t1 · cc7239b2
      Magne Mahre authored
                        
      An error occuring in the execution of a stored procedure, called
      from do_select is masked, since the error condition is not
      propagated back to the caller (join->conds->val_int() returns
      a result value, and not an error code)
                        
      An explicit check was added to see if the thd error code has been
      set, and if so, the loop status is set to the error state.
      
      Backport from 6.0-codebase (revid: 2617.68.31)
      cc7239b2
    • Magne Mahre's avatar
      Bug#41425 Assertion in Protocol::end_statement() (pushbuild2) · 16f31515
      Magne Mahre authored
                (diagnostics_area)
            
      Execution of CREATE TABLE ... SELECT statement was not atomic in
      the sense that concurrent statements trying to affect its target
      table might have sneaked in between the moment when the table was
      created and moment when it was filled according to SELECT clause.
      This resulted in inconsistent binary log, unexpected target table
      contents. In cases when concurrent statement was a DDL statement
      CREATE TABLE ... SELECT might have failed with ER_CANT_LOCK error.
            
      In more detail:
      Due to premature metadata lock downgrade which occured after CREATE
      TABLE SELECT statement created table but before it managed to obtain
      table-level lock on it other statements were allowed to open, lock
      and change target table in the middle of CREATE TABLE SELECT
      execution. This also meant that it was possible that CREATE TABLE
      SELECT would wait in mysql_lock_tables() when it was called for newly
      created table and that this wait could have been aborted by concurrent
      DDL. The latter led to execution of unexpected branch of code and
      CREATE TABLE SELECT ending with ER_CANT_LOCK error.
            
      The premature downgrade occured because open_table(), which was called
      for newly created table, decided that it is OK to downgrade metadata
      lock from exclusive to shared since table exists, even although it
      was not acquired within this call.
            
      This fix ensures that open_table() does not downgrade metadata lock
      if it is not acquired during its current invocation.
            
      Testing:
      The bug is exposed in a race condition, and is thus difficult to
      expose in a standard mysql-test-run test case.  Instead, a stress
      test using the Random Query Generator (https://launchpad.net/randgen)
      will trip the problem occasionally.
            
         % perl  runall.pl \
                  --basedir=<build dir> \
                   --mysqld=--table-lock-wait-timeout=5 \
                   --mysqld=--skip-safemalloc \
                   --grammar=conf/maria_bulk_insert.yy \
                   --reporters=ErrorLog,Backtrace,WinPackage \
                   --mysqld=--log-output=file  \
                   --queries=100000 \
                   --threads=10 \
                   --engine=myisam
            
      Note: You will need a debug build to expose the bug
            
      When the bug is tripped, the server will abort and dump core.
      
      
      Backport from 6.0-codebase   (revid: 2617.53.4)
      16f31515
    • Jon Olav Hauglid's avatar
      Backport of revno: 3690 · 94154c95
      Jon Olav Hauglid authored
      Postfix for Bug#48210 FLUSH TABLES WITH READ LOCK deadlocks
                            against concurrent CREATE PROCEDURE
      
      Rewrote the second test to use DROP PROCEDURE instead of 
      CREATE USER as CREATE USER does not work with embedded server.
      94154c95
    • Jon Olav Hauglid's avatar
      Backport of revno: 3685 · 3d062adf
      Jon Olav Hauglid authored
      Bug #48210 FLUSH TABLES WITH READ LOCK deadlocks
                 against concurrent CREATE PROCEDURE
      
      This deadlock occured between
      a) CREATE PROCEDURE (or other commands listed below)
      b) FLUSH TABLES WITH READ LOCK
      
      If the execution of them happened in the following order:
      - a) opens a table (e.g. mysql.proc)
      - b) locks the global read lock (or GRL)
      - a) sleeps inside wait_if_global_read_lock()
      - b) increases refresh_version and sleeps waiting 
           for old tables to go away
      
      Note that a) must start waiting on the GRL before FLUSH increases
      refresh_version. Otherwise a) won't wait on the GRL and instead
      close its tables for reopen, allowing FLUSH to complete and thus
      avoid the deadlock.
      
      With this patch the deadlock is avoided by making CREATE PROCEDURE
      acquire a protection against global read locks before it starts
      executing. This means that FLUSH TABLES WITH READ LOCK will have
      to wait until CREATE PROCEDURE completes before acquiring the global
      read lock, thereby avoiding the deadlock.
      
      This is implemented by introducing a new SQL command flag called
      CF_PROTECT_AGAINST_GRL. Commands marked with this flag will
      acquire a GRL protection in the beginning of mysql_execute_command().
      This patch adds the flag to CREATE, ALTER and DROP for PROCEDURE
      and FUNCTION, as well as CREATE USER, DROP USER, RENAME USER and 
      REVOKE ALL. All these commands either call open_grant_tables() or
      open_system_table_for_updated() which make them susceptible for
      this deadlock.
      
      The patch also adds the CF_PROTECT_AGAINST_GRL flag to a number
      of commands that previously acquired GRL protection in their
      respective SQLCOM case in mysql_execute_command().
      
      Test case that checks for GRL protection for CREATE PROCEDURE
      and CREATE USER added to mdl_sync.test.
      3d062adf
    • Konstantin Osipov's avatar
      Backport of: · 2f7a8770
      Konstantin Osipov authored
       2630.16.14 Sergei Golubchik	2008-08-25
       fixed a crash in partition tests
       introduced by HA_EXTRA_PREPARE_FOR_DROP patch
      
      
      sql/sql_base.cc:
        Don't call ::extra() for closed tables.
      2f7a8770
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.80.1 · 6c13f657
      Jon Olav Hauglid authored
      Also re-enables the test for Bug #43867
      
      Followup to Bug#46654 False deadlock on concurrent DML/DDL with partitions, 
                            inconsistent behavior
      
      Partition_sync.test uses features only available in debug builds.
      Disabling the test for non-debug builds.
      6c13f657
    • Konstantin Osipov's avatar
      Backport a part of Monty's fix for Bug#39396, rev. 2736.2.11 · f8055175
      Konstantin Osipov authored
      "ha_maria.cc:2415: assertion in ha_maria::store_lock()".
      
      sql/lock.cc:
        Fixed wrong cleanup of mysql_lock_tables()
        - We must call read_lock_data() BEFORE we set 
        lock_count to 0. Added DBUG statements.
      f8055175
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.37 · fb6b5ee4
      Jon Olav Hauglid authored
      Bug #46654 False deadlock on concurrent DML/DDL with partitions, 
                 inconsistent behavior
      
      The problem was that if one connection is running a multi-statement 
      transaction which involves a single partitioned table, and another 
      connection attempts to alter the table, the first connection gets 
      ER_LOCK_DEADLOCK and cannot proceed anymore, even when the ALTER TABLE 
      statement in another connection has timed out or failed.
      
      The reason for this was that the prepare phase for ALTER TABLE for 
      partitioned tables removed all instances of the table from the table 
      definition cache before it started waiting on the lock. The transaction 
      running in the first connection would notice this and report ER_LOCK_DEADLOCK. 
      
      This patch changes the prep_alter_part_table() ALTER TABLE code so that 
      tdc_remove_table() is no longer called. Instead, only the TABLE instance
      changed by prep_alter_part_table() is marked as needing reopen.
      
      The patch also removes an unnecessary call to tdc_remove_table() from 
      mysql_unpack_partition() as the changed TABLE object is destroyed by the 
      caller at a later point.
      
      Test case added in partition_sync.test.
      fb6b5ee4
    • Jon Olav Hauglid's avatar
      Backport of revno: 3514 · 7d71d715
      Jon Olav Hauglid authored
      Bug#40181 Made use of tdc_remove_table instead of just 
      setting share->version to 0 to make sure all unused table
      instances go away as part of CREATE/ALTER TABLE.
      7d71d715
    • Jon Olav Hauglid's avatar
      Backport of revno: 3673 · 58a9857b
      Jon Olav Hauglid authored
      Bug #47313 assert in check_key_in_view during CALL procedure
      
      View definitions are inlined in a stored procedure when the procedure
      is fist called. This means that if a temporary table is later added
      with the same name as the view, the stored procedure will still
      use the view. This happens even if temporary tables normally shadow
      base tables/views.
      
      The reason for the assert was that even if the stored procedure
      referenced the view, open_table() still tried to open the
      temporary table. This "half view/half temporary table" state
      caused the assert.
      
      The bug was not present in 5.1 as open_table() is not called
      for the view there. This code was changed with the introduction 
      of MDL in order to properly lock the view and any objects it 
      refers to.
      
      This patch fixes the problem by instructing open_table()
      to open base tables/views (using OT_BASE_ONLY) when reopening
      tables/views used by stored procedures. This also means that
      a prepared statement is no longer invalidated if a temporary
      table is created with the same name as a view used in the
      prepared statement.
      
      Test case added to sp.test. The test case also demonstrates
      the effect of sp cache invalidation between CALLs.
      
      
      mysql-test/t/ps_ddl.test:
        Extended the VIEW->TEMPORARY TABLE transition test to cover not only
        merged views, but now also materialized views and views containing
        a reference to an information schema table. 
        
        Test also updated to reflect the change to prepared statement
        invalidatation.
      58a9857b
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.45 · 69f677b2
      Jon Olav Hauglid authored
      Bug #47635 assert in start_waiting_global_read_lock during CREATE VIEW
      
      The problem was that CREATE VIEW would trigger an assert if
      a temporary table with the same name already existed.
      
      This bug was fixed by the patch for Bug#47335. CREATE/ALTER VIEW
      will now ignore temporary tables. See Bug#47335 for more information.
      
      Test case added to view.test.
      69f677b2
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.43 · 0b874e3e
      Jon Olav Hauglid authored
      Bug #47335 assert in get_table_share
      
      The assert would happen if ALTER VIEW was used to alter a view (existing 
      or non-existing) and a temporary table with the same name already existed.
      
      The assert is triggered if the current statement does not have a MDL lock on 
      the view to be altered. This would happen because open_table() would open 
      the temporary table instead and MDL locks are not taken for temporary 
      tables (since they are local to one connection).
      
      The patch changes open_type for CREATE/ALTER VIEW to OT_BASE_ONLY. This prevents 
      open_table() from trying to open a temporary table with the same name should
      one exist. Now the view will be altered if it exists or ER_NO_SUCH_TABLE will
      be reported if it does not.
      
      Test case added to view.test
      0b874e3e
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.3 · 84e35f5e
      Jon Olav Hauglid authored
      Followup to Bug#42546 Backup: RESTORE fails, thinking it finds an existing table
      
      This patch updates lowercase_table2.test with the changed error message
      CREATE TABLE produces if it fails because it finds an matching TABLE_SHARE 
      in the TDC even if the .FRM/.MYD has been removed from disk.
      
      With the changes introduced in Bug#42546, CREATE TABLE uses open_tables()
      which will find the TDC entry and fail in open_table_from_share() with
      ER_FILE_NOT_FOUND. Before, CREATE TABLE would not use open_tables() and
      fail with ER_TABLE_EXISTS_ERROR upon finding the TDC entry in
      mysql_create_table_no_lock().
      84e35f5e
    • 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
  3. 09 Dec, 2009 18 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