1. 16 Dec, 2009 2 commits
  2. 15 Dec, 2009 4 commits
    • Konstantin Osipov's avatar
      Merge next-mr -> next-4284. · 34177cc9
      Konstantin Osipov authored
      34177cc9
    • Konstantin Osipov's avatar
      Merge next-mr -> next-4284. · 75fa4b6a
      Konstantin Osipov authored
      75fa4b6a
    • Konstantin Osipov's avatar
      Merge next-mr -> next-4284. · a16c0512
      Konstantin Osipov authored
      a16c0512
    • Jon Olav Hauglid's avatar
      Bug #48940 MDL deadlocks against mysql_rm_db · a4d01b7c
      Jon Olav Hauglid authored
      This deadlock would occur between two connections A and B if statements
      where executed in the following way:
      1) Connection A executes a DML statement against table s1.t1 with
      autocommit off. This causes a shared metadata lock on s1.t1 to be 
      acquired. (With autocommit on, the metadata lock will be dropped once
      the statment completes and the deadlock will not occour.)
      2) Connection B tries to DROP DATABASE s1. This will block against the
      metadata lock connection A holds on s1.t1. While blocking, connection B
      will hold the LOCK_mysql_create_db mutex.
      3) Connection A tries to ALTER DATABASE s1. This will block when trying
      to get LOCK_mysql_create_db mutex held by connection B.
      4) Deadlock between DROP DATABASE and ALTER DATABASE (which has autocommit
      off).
      
      If Connection A used an explicitly started transaction rather than having
      autocommit off, this deadlock did not happen as ALTER DATABASE is 
      disallowed inside transactions.
      
      This patch fixes the problem by changing ALTER DATABASE to cause an
      implicit commit before executing. This will cause the metadata 
      lock on s1.t1 to be dropped, allowing DROP DATABASE to proceed. 
      This will in turn cause the LOCK_mysql_create_db mutex to be unlocked, 
      allowing ALTER DATABASE to proceed.
      
      Note that SQL commands other than ALTER DATABASE that also use 
      LOCK_mysql_create_db, already cause an implicit commit. 
      
      Incompatible change: ALTER DATABASE (and its synonym ALTER SCHEMA)
      now cause an implicit commit. This must be reflected in the 
      documentation.
      
      Test case added to schema.test.
      
      
      sql/sql_parse.cc:
        Added CF_AUTO_COMMIT_TRANS to SQLCOM_ALTER_DB.
        
        Removed thd->active_transaction() checks from SQLCOM_DROP_DB, 
        SQLCOM_ALTER_DB_UPGRADE and SQLCOM_ALTER_DB as these statements
        cause an implicit commit.
      a4d01b7c
  3. 11 Dec, 2009 5 commits
    • Konstantin Osipov's avatar
      Backport of: · e4127942
      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.
      e4127942
    • Konstantin Osipov's avatar
      Backport of: · 6dc51c81
      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).
      6dc51c81
    • Konstantin Osipov's avatar
      Partial backport of: · 9f37eecd
      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.
      9f37eecd
    • Konstantin Osipov's avatar
      Partial backport of: · 25793f1e
      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.
      25793f1e
    • Konstantin Osipov's avatar
      Merge with next-4284. · 3ca7625f
      Konstantin Osipov authored
      3ca7625f
  4. 10 Dec, 2009 18 commits
    • Magne Mahre's avatar
      Bug#46374 crash, INSERT INTO t1 uses function, function modifies t1 · 2930b825
      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)
      2930b825
    • Magne Mahre's avatar
      Bug#41425 Assertion in Protocol::end_statement() (pushbuild2) · d23b9ff1
      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)
      d23b9ff1
    • Jon Olav Hauglid's avatar
      Backport of revno: 3690 · f797ba9e
      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.
      f797ba9e
    • Jon Olav Hauglid's avatar
      Backport of revno: 3685 · 7696a241
      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.
      7696a241
    • Konstantin Osipov's avatar
      Backport of: · 60372471
      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.
      60372471
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.80.1 · 2768ed9f
      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.
      2768ed9f
    • Konstantin Osipov's avatar
      Backport a part of Monty's fix for Bug#39396, rev. 2736.2.11 · 569c31f4
      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.
      569c31f4
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.37 · a7dbba6e
      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.
      a7dbba6e
    • Jon Olav Hauglid's avatar
      Backport of revno: 3514 · 38f010b2
      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.
      38f010b2
    • Jon Olav Hauglid's avatar
      Backport of revno: 3673 · 91af324f
      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.
      91af324f
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.45 · 16f5800d
      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.
      16f5800d
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.43 · 49c76ae7
      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
      49c76ae7
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.3 · 0c5786f4
      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().
      0c5786f4
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.71.1 · 1f09da44
      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.
      1f09da44
    • Magne Mahre's avatar
      Bug #46495 Crash in reload_acl_and_cache on SIGHUP · 23f7db77
      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)
      
      23f7db77
    • Sergey Vojtovich's avatar
    • Konstantin Osipov's avatar
      Merge with next-4284. · 65ded56f
      Konstantin Osipov authored
      65ded56f
    • Konstantin Osipov's avatar
      Backport of: · bcc9473e
      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).
      bcc9473e
  5. 09 Dec, 2009 11 commits
    • Konstantin Osipov's avatar
      Backport of: · 4103e125
      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.
      4103e125
    • Konstantin Osipov's avatar
      ------------------------------------------------------------ · 38798f9b
      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.
      38798f9b
    • Konstantin Osipov's avatar
      Backport of: · 02429481
      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.
      02429481
    • Konstantin Osipov's avatar
      Backport of: · af1561a8
      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.
      af1561a8
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.18 · e53498b5
      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.
      e53498b5
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.68.13 · ca5cd40c
      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.
      ca5cd40c
    • unknown's avatar
      Backport of revno: 2617.68.36 · 3386aa46
      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.
      3386aa46
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.31.30 · b97beb08
      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.
      b97beb08
    • Jon Olav Hauglid's avatar
      Backport of revno: 3702 · 304afa04
      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.
      304afa04
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.76.3 · 6d5a1cf7
      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.
      6d5a1cf7
    • Jon Olav Hauglid's avatar
      Backport of revno: 2617.76.2 · faf5bea5
      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.
      faf5bea5