List:Commits« Previous MessageNext Message »
From:Jon Olav Hauglid Date:October 12 2011 3:56pm
Subject:bzr push into mysql-trunk-wl5534 branch (jon.hauglid:3403 to 3404) WL#5534
View as plain text  
 3404 Jon Olav Hauglid	2011-10-12
      WL#5534 Online ALTER, Phase 1.
        
      Patch #32:
      This patch introduces the metadata locking changes needed in
      order to support online ALTER TABLE. It introduces
      MDL_SHARED_UPGRADABLE lock which blocks DDL, allows DML and is
      upgradable. This locking level is now initially used for ALTER
      TABLE. When supported, it is also used for in-place operations.

    modified:
      mysql-test/r/mdl_sync.result
      mysql-test/suite/perfschema/r/stage_mdl_table.result
      mysql-test/t/mdl_sync.test
      sql/mdl.cc
      sql/mdl.h
      sql/sql_base.cc
      sql/sql_partition.cc
      sql/sql_partition_admin.cc
      sql/sql_table.cc
      sql/sql_trigger.cc
      sql/sql_truncate.cc
      sql/sql_yacc.yy
      storage/myisammrg/ha_myisammrg.cc
      unittest/gunit/mdl-t.cc
      unittest/gunit/mdl_mytap-t.cc
 3403 Jon Olav Hauglid	2011-10-12
      WL#5534 Online ALTER, Phase 1.
        
      Patch #31:
      Various refactorings:
      - Remove unused variables and parameters.
      - Delay variable definitions.
      - Reduce goto usage

    modified:
      sql/sql_partition.cc
      sql/sql_partition.h
      sql/sql_table.cc
=== modified file 'mysql-test/r/mdl_sync.result'
--- a/mysql-test/r/mdl_sync.result	2011-02-21 02:57:30 +0000
+++ b/mysql-test/r/mdl_sync.result	2011-10-12 15:55:19 +0000
@@ -400,9 +400,9 @@ rename table t2 to t1;
 # 5) Acquire SNW lock on the table. We have to use DEBUG_SYNC for
 #    this, to prevent SNW from being immediately upgraded to X.
 #
-set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish';
 # Sending:
-alter table t1 add primary key (c1);;
+alter table t1 add primary key (c1), lock=shared, algorithm=copy;;
 # 
 # Switching to connection 'mdl_con1'.
 set debug_sync= 'now WAIT_FOR locked';
@@ -482,9 +482,9 @@ insert into t1 values (1);
 unlock tables;
 # 
 # Switching to connection 'default'.
-set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish';
 # Sending:
-alter table t1 add primary key (c1);;
+alter table t1 add primary key (c1), algorithm=copy, lock=shared;;
 # 
 # Switching to connection 'mdl_con1'.
 set debug_sync= 'now WAIT_FOR locked';
@@ -1154,9 +1154,9 @@ count(*)
 # We have to use DEBUG_SYNC facility as otherwise SNW lock
 # will be immediately released (or upgraded to X lock).
 insert into t2 values (1), (1);
-set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish';
 # Sending:
-alter table t2 add primary key (c1);;
+alter table t2 add primary key (c1), algorithm=copy, lock=shared;;
 # 
 # Switching to connection 'default'.
 set debug_sync= 'now WAIT_FOR locked';
@@ -1199,9 +1199,9 @@ count(*)
 # 
 # Switching to connection 'mdl_con1'.
 # Create an active SNW lock on t1.
-set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish';
 # Sending:
-alter table t1 add primary key (c1);;
+alter table t1 add primary key (c1), algorithm=copy, lock=shared;;
 # 
 # Switching to connection 'default'.
 set debug_sync= 'now WAIT_FOR locked';
@@ -1986,7 +1986,7 @@ drop tables t1, t2;
 #
 create table t1 (i int);
 # Ensure that ALTER waits once it has acquired SNW lock.
-set debug_sync='after_open_table_mdl_shared SIGNAL parked1 WAIT_FOR go1';
+set debug_sync='alter_table_copy_after_lock_upgrade SIGNAL parked1 WAIT_FOR go1';
 # Sending:
 alter table t1 add column j int;
 #
@@ -2435,7 +2435,7 @@ c1	c2	c3
 3	3	0
 #
 # Switching to connection 'con46273'.
-set debug_sync='after_lock_tables_takes_lock SIGNAL alter_table_locked WAIT_FOR alter_go';
+set debug_sync='alter_table_copy_after_lock_upgrade SIGNAL alter_table_locked WAIT_FOR alter_go';
 alter table t1 add column e int, rename to t2;;
 #
 # Switching to connection 'default'.
@@ -2579,7 +2579,7 @@ drop table if exists t1;
 set debug_sync= 'RESET';
 create table t1 (i int) engine=InnoDB;
 # Switching to connection 'con50913_1'.
-set debug_sync= 'thr_multi_lock_after_thr_lock SIGNAL parked WAIT_FOR go';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL parked WAIT_FOR go';
 # Sending:
 alter table t1 add column j int;
 # Switching to connection 'default'.
@@ -2621,7 +2621,7 @@ i
 # Switching to connection 'default'.
 # Start ALTER TABLE which will acquire SNW lock and
 # table lock and get blocked on sync point.
-set debug_sync= 'thr_multi_lock_after_thr_lock SIGNAL parked WAIT_FOR go';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL parked WAIT_FOR go';
 # Sending:
 alter table t1 add column j int;
 # Switching to connection 'con1'.
@@ -2955,12 +2955,16 @@ CREATE TABLE m1(a INT) engine=MERGE UNIO
 INSERT INTO t1 VALUES (1), (2);
 INSERT INTO t2 VALUES (3), (4);
 # Connection con1
-SET DEBUG_SYNC= 'mdl_upgrade_shared_lock_to_exclusive SIGNAL upgrade WAIT_FOR continue';
+# We need EXECUTE 2 since ALTER TABLE does SU => SNW => X and we want
+# to stop at the second upgrade.
+SET DEBUG_SYNC= 'mdl_upgrade_shared_lock_to_exclusive SIGNAL upgrade WAIT_FOR continue EXECUTE 2';
 # Sending:
 ALTER TABLE m1 engine=MERGE UNION=(t2, t1);
 # Connection con2
 # Waiting for ALTER TABLE to try lock upgrade
 SET DEBUG_SYNC= 'now WAIT_FOR upgrade';
+SET DEBUG_SYNC= 'now SIGNAL continue';
+SET DEBUG_SYNC= 'now WAIT_FOR upgrade';
 # Sending:
 DELETE FROM t2 WHERE a = 3;
 # Connection default

=== modified file 'mysql-test/suite/perfschema/r/stage_mdl_table.result'
--- a/mysql-test/suite/perfschema/r/stage_mdl_table.result	2011-07-21 16:27:14 +0000
+++ b/mysql-test/suite/perfschema/r/stage_mdl_table.result	2011-10-12 15:55:19 +0000
@@ -34,4 +34,6 @@ user2	stage/sql/checking permissions	STA
 user2	stage/sql/checking permissions	STATEMENT
 user2	stage/sql/init	STATEMENT
 user2	stage/sql/Opening tables	STATEMENT
+user2	stage/sql/System lock	STATEMENT
+user2	stage/sql/setup	STATEMENT
 commit;

=== modified file 'mysql-test/t/mdl_sync.test'
--- a/mysql-test/t/mdl_sync.test	2011-02-21 02:57:30 +0000
+++ b/mysql-test/t/mdl_sync.test	2011-10-12 15:55:19 +0000
@@ -573,9 +573,9 @@ connection default;
 --echo # 5) Acquire SNW lock on the table. We have to use DEBUG_SYNC for
 --echo #    this, to prevent SNW from being immediately upgraded to X.
 --echo #
-set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish';
 --echo # Sending:
---send alter table t1 add primary key (c1);
+--send alter table t1 add primary key (c1), lock=shared, algorithm=copy;
 --echo # 
 --echo # Switching to connection 'mdl_con1'.
 connection mdl_con1;
@@ -687,9 +687,9 @@ unlock tables;
 --echo # 
 --echo # Switching to connection 'default'.
 connection default;
-set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish';
 --echo # Sending:
---send alter table t1 add primary key (c1);
+--send alter table t1 add primary key (c1), algorithm=copy, lock=shared;
 --echo # 
 --echo # Switching to connection 'mdl_con1'.
 connection mdl_con1;
@@ -1673,9 +1673,9 @@ connection mdl_con1;
 --echo # We have to use DEBUG_SYNC facility as otherwise SNW lock
 --echo # will be immediately released (or upgraded to X lock).
 insert into t2 values (1), (1);
-set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish';
 --echo # Sending:
---send alter table t2 add primary key (c1);
+--send alter table t2 add primary key (c1), algorithm=copy, lock=shared;
 --echo # 
 --echo # Switching to connection 'default'.
 connection default;
@@ -1724,9 +1724,9 @@ select count(*) from t1;
 --echo # Switching to connection 'mdl_con1'.
 connection mdl_con1;
 --echo # Create an active SNW lock on t1.
-set debug_sync= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL locked WAIT_FOR finish';
 --echo # Sending:
---send alter table t1 add primary key (c1);
+--send alter table t1 add primary key (c1), algorithm=copy, lock=shared;
 --echo # 
 --echo # Switching to connection 'default'.
 connection default;
@@ -2845,7 +2845,7 @@ drop tables t1, t2;
 create table t1 (i int);
 
 --echo # Ensure that ALTER waits once it has acquired SNW lock.
-set debug_sync='after_open_table_mdl_shared SIGNAL parked1 WAIT_FOR go1';
+set debug_sync='alter_table_copy_after_lock_upgrade SIGNAL parked1 WAIT_FOR go1';
 --echo # Sending:
 --send alter table t1 add column j int
 
@@ -3634,7 +3634,7 @@ select * from t1 where c2 = 3;
 --echo #
 --echo # Switching to connection 'con46273'.
 connection con46273;
-set debug_sync='after_lock_tables_takes_lock SIGNAL alter_table_locked WAIT_FOR alter_go';
+set debug_sync='alter_table_copy_after_lock_upgrade SIGNAL alter_table_locked WAIT_FOR alter_go';
 --send alter table t1 add column e int, rename to t2;
 
 --echo #
@@ -3897,7 +3897,7 @@ create table t1 (i int) engine=InnoDB;
 
 --echo # Switching to connection 'con50913_1'.
 connection con50913_1;
-set debug_sync= 'thr_multi_lock_after_thr_lock SIGNAL parked WAIT_FOR go';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL parked WAIT_FOR go';
 --echo # Sending:
 --send alter table t1 add column j int
 
@@ -3968,7 +3968,7 @@ select * from t1;
 connection default;
 --echo # Start ALTER TABLE which will acquire SNW lock and
 --echo # table lock and get blocked on sync point.
-set debug_sync= 'thr_multi_lock_after_thr_lock SIGNAL parked WAIT_FOR go';
+set debug_sync= 'alter_table_copy_after_lock_upgrade SIGNAL parked WAIT_FOR go';
 --echo # Sending:
 --send alter table t1 add column j int
 
@@ -4633,7 +4633,9 @@ connect(con2, localhost, root);
 
 --echo # Connection con1
 connection con1;
-SET DEBUG_SYNC= 'mdl_upgrade_shared_lock_to_exclusive SIGNAL upgrade WAIT_FOR continue';
+--echo # We need EXECUTE 2 since ALTER TABLE does SU => SNW => X and we want
+--echo # to stop at the second upgrade.
+SET DEBUG_SYNC= 'mdl_upgrade_shared_lock_to_exclusive SIGNAL upgrade WAIT_FOR continue EXECUTE 2';
 --echo # Sending:
 --send ALTER TABLE m1 engine=MERGE UNION=(t2, t1)
 
@@ -4641,6 +4643,8 @@ SET DEBUG_SYNC= 'mdl_upgrade_shared_lock
 connection con2;
 --echo # Waiting for ALTER TABLE to try lock upgrade
 SET DEBUG_SYNC= 'now WAIT_FOR upgrade';
+SET DEBUG_SYNC= 'now SIGNAL continue';
+SET DEBUG_SYNC= 'now WAIT_FOR upgrade';
 --echo # Sending:
 --send DELETE FROM t2 WHERE a = 3
 

=== modified file 'sql/mdl.cc'
--- a/sql/mdl.cc	2011-07-21 16:27:14 +0000
+++ b/sql/mdl.cc	2011-10-12 15:55:19 +0000
@@ -293,7 +293,7 @@ Deadlock_detection_visitor::opt_change_v
 class MDL_lock
 {
 public:
-  typedef uchar bitmap_t;
+  typedef unsigned short bitmap_t;
 
   class Ticket_list
   {
@@ -900,7 +900,7 @@ void MDL_ticket::destroy(MDL_ticket *tic
 uint MDL_ticket::get_deadlock_weight() const
 {
   return (m_lock->key.mdl_namespace() == MDL_key::GLOBAL ||
-          m_type >= MDL_SHARED_NO_WRITE ?
+          m_type >= MDL_SHARED_UPGRADABLE ?
           DEADLOCK_WEIGHT_DDL : DEADLOCK_WEIGHT_DML);
 }
 
@@ -1165,13 +1165,13 @@ void MDL_lock::reschedule_waiters()
 
   Here is how types of individual locks are translated to type of scoped lock:
 
-    ----------------+-------------+
-    Type of request | Correspond. |
-    for indiv. lock | scoped lock |
-    ----------------+-------------+
-    S, SH, SR, SW   |   IS        |
-    SNW, SNRW, X    |   IX        |
-    SNW, SNRW -> X  |   IX (*)    |
+    --------------------+-------------+
+    Type of request     | Correspond. |
+    for indiv. lock     | scoped lock |
+    --------------------+-------------+
+    S, SH, SR, SW       |   IS        |
+    SU, SNW, SNRW, X    |   IX        |
+    SU, SNW, SNRW -> X  |   IX (*)    |
 
   The first array specifies if particular type of request can be satisfied
   if there is granted scoped lock of certain type.
@@ -1211,14 +1211,14 @@ void MDL_lock::reschedule_waiters()
 const MDL_lock::bitmap_t MDL_scoped_lock::m_granted_incompatible[MDL_TYPE_END] =
 {
   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
-  MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_INTENTION_EXCLUSIVE), 0, 0, 0, 0, 0,
+  MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_INTENTION_EXCLUSIVE), 0, 0, 0, 0, 0, 0,
   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED) | MDL_BIT(MDL_INTENTION_EXCLUSIVE)
 };
 
 const MDL_lock::bitmap_t MDL_scoped_lock::m_waiting_incompatible[MDL_TYPE_END] =
 {
   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
-  MDL_BIT(MDL_EXCLUSIVE), 0, 0, 0, 0, 0, 0
+  MDL_BIT(MDL_EXCLUSIVE), 0, 0, 0, 0, 0, 0, 0
 };
 
 
@@ -1230,35 +1230,39 @@ const MDL_lock::bitmap_t MDL_scoped_lock
   The first array specifies if particular type of request can be satisfied
   if there is granted lock of certain type.
 
-     Request  |  Granted requests for lock   |
-      type    | S  SH  SR  SW  SNW  SNRW  X  |
-    ----------+------------------------------+
-    S         | +   +   +   +   +    +    -  |
-    SH        | +   +   +   +   +    +    -  |
-    SR        | +   +   +   +   +    -    -  |
-    SW        | +   +   +   +   -    -    -  |
-    SNW       | +   +   +   -   -    -    -  |
-    SNRW      | +   +   -   -   -    -    -  |
-    X         | -   -   -   -   -    -    -  |
-    SNW -> X  | -   -   -   0   0    0    0  |
-    SNRW -> X | -   -   0   0   0    0    0  |
+     Request  |  Granted requests for lock       |
+      type    | S  SH  SR  SW  SU  SNW  SNRW  X  |
+    ----------+----------------------------------+
+    S         | +   +   +   +   +   +    +    -  |
+    SH        | +   +   +   +   +   +    +    -  |
+    SR        | +   +   +   +   +   +    -    -  |
+    SW        | +   +   +   +   +   -    -    -  |
+    SU        | +   +   +   +   -   -    -    -  |
+    SNW       | +   +   +   -   -   -    -    -  |
+    SNRW      | +   +   -   -   -   -    -    -  |
+    X         | -   -   -   -   -   -    -    -  |
+    SU -> X   | -   -   -   -   0   0    0    0  |
+    SNW -> X  | -   -   -   0   0   0    0    0  |
+    SNRW -> X | -   -   0   0   0   0    0    0  |
 
   The second array specifies if particular type of request can be satisfied
   if there is waiting request for the same lock of certain type. In other
   words it specifies what is the priority of different lock types.
 
-     Request  |  Pending requests for lock  |
-      type    | S  SH  SR  SW  SNW  SNRW  X |
-    ----------+-----------------------------+
-    S         | +   +   +   +   +     +   - |
-    SH        | +   +   +   +   +     +   + |
-    SR        | +   +   +   +   +     -   - |
-    SW        | +   +   +   +   -     -   - |
-    SNW       | +   +   +   +   +     +   - |
-    SNRW      | +   +   +   +   +     +   - |
-    X         | +   +   +   +   +     +   + |
-    SNW -> X  | +   +   +   +   +     +   + |
-    SNRW -> X | +   +   +   +   +     +   + |
+     Request  |  Pending requests for lock      |
+      type    | S  SH  SR  SW  SU  SNW  SNRW  X |
+    ----------+---------------------------------+
+    S         | +   +   +   +   +   +     +   - |
+    SH        | +   +   +   +   +   +     +   + |
+    SR        | +   +   +   +   +   +     -   - |
+    SW        | +   +   +   +   +   -     -   - |
+    SU        | +   +   +   +   +   +     +   - |
+    SNW       | +   +   +   +   +   +     +   - |
+    SNRW      | +   +   +   +   +   +     +   - |
+    X         | +   +   +   +   +   +     +   + |
+    SU -> X   | +   +   +   +   +   +     +   + |
+    SNW -> X  | +   +   +   +   +   +     +   + |
+    SNRW -> X | +   +   +   +   +   +     +   + |
 
   Here: "+" -- means that request can be satisfied
         "-" -- means that request can't be satisfied and should wait
@@ -1279,14 +1283,17 @@ MDL_object_lock::m_granted_incompatible[
   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
     MDL_BIT(MDL_SHARED_NO_WRITE),
   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
-    MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_WRITE),
+    MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE),
   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
-    MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_WRITE) |
-    MDL_BIT(MDL_SHARED_READ),
+    MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
+    MDL_BIT(MDL_SHARED_WRITE),
   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
-    MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_WRITE) |
-    MDL_BIT(MDL_SHARED_READ) | MDL_BIT(MDL_SHARED_HIGH_PRIO) |
-    MDL_BIT(MDL_SHARED)
+    MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
+    MDL_BIT(MDL_SHARED_WRITE) | MDL_BIT(MDL_SHARED_READ),
+  MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
+    MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
+    MDL_BIT(MDL_SHARED_WRITE) | MDL_BIT(MDL_SHARED_READ) |
+    MDL_BIT(MDL_SHARED_HIGH_PRIO) | MDL_BIT(MDL_SHARED)
 };
 
 
@@ -1301,6 +1308,7 @@ MDL_object_lock::m_waiting_incompatible[
     MDL_BIT(MDL_SHARED_NO_WRITE),
   MDL_BIT(MDL_EXCLUSIVE),
   MDL_BIT(MDL_EXCLUSIVE),
+  MDL_BIT(MDL_EXCLUSIVE),
   0
 };
 
@@ -1696,7 +1704,7 @@ MDL_context::clone_ticket(MDL_request *m
 
 /**
   Notify threads holding a shared metadata locks on object which
-  conflict with a pending X, SNW or SNRW lock.
+  conflict with a pending X, SU, SNW or SNRW lock.
 
   @param  ctx  MDL_context for current thread.
 */
@@ -1710,7 +1718,7 @@ void MDL_object_lock::notify_conflicting
   {
     /* Only try to abort locks on which we back off. */
     if (conflicting_ticket->get_ctx() != ctx &&
-        conflicting_ticket->get_type() < MDL_SHARED_NO_WRITE)
+        conflicting_ticket->get_type() < MDL_SHARED_UPGRADABLE)
 
     {
       MDL_context *conflicting_ctx= conflicting_ticket->get_ctx();
@@ -1970,11 +1978,12 @@ err:
 
 
 /**
-  Upgrade a shared metadata lock to exclusive.
+  Upgrade a shared metadata lock.
 
-  Used in ALTER TABLE, when a copy of the table with the
-  new definition has been constructed.
+  Used in ALTER TABLE.
 
+  @param mdl_ticket         Lock to upgrade.
+  @param new_type           Lock type to upgrade to.
   @param lock_wait_timeout  Seconds to wait before timeout.
 
   @note In case of failure to upgrade lock (e.g. because upgrader
@@ -1982,7 +1991,7 @@ err:
         shared mode).
 
   @note There can be only one upgrader for a lock or we will have deadlock.
-        This invariant is ensured by the fact that upgradeable locks SNW
+        This invariant is ensured by the fact that upgradeable locks SU, SNW
         and SNRW are not compatible with each other and themselves.
 
   @retval FALSE  Success
@@ -1990,28 +1999,33 @@ err:
 */
 
 bool
-MDL_context::upgrade_shared_lock_to_exclusive(MDL_ticket *mdl_ticket,
-                                              ulong lock_wait_timeout)
+MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket,
+                                 enum_mdl_type new_type,
+                                 ulong lock_wait_timeout)
 {
   MDL_request mdl_xlock_request;
   MDL_savepoint mdl_svp= mdl_savepoint();
   bool is_new_ticket;
 
-  DBUG_ENTER("MDL_ticket::upgrade_shared_lock_to_exclusive");
+  DBUG_ENTER("MDL_ticket::upgrade_shared_lock");
   DEBUG_SYNC(get_thd(), "mdl_upgrade_shared_lock_to_exclusive");
 
   /*
     Do nothing if already upgraded. Used when we FLUSH TABLE under
     LOCK TABLES and a table is listed twice in LOCK TABLES list.
   */
-  if (mdl_ticket->m_type == MDL_EXCLUSIVE)
+  if (mdl_ticket->has_stronger_or_equal_type(new_type))
     DBUG_RETURN(FALSE);
 
-  /* Only allow upgrades from MDL_SHARED_NO_WRITE/NO_READ_WRITE */
-  DBUG_ASSERT(mdl_ticket->m_type == MDL_SHARED_NO_WRITE ||
+  /* Only allow upgrades from SHARED_UPGRADABLE/NO_WRITE/NO_READ_WRITE */
+  DBUG_ASSERT(mdl_ticket->m_type == MDL_SHARED_UPGRADABLE ||
+              mdl_ticket->m_type == MDL_SHARED_NO_WRITE ||
               mdl_ticket->m_type == MDL_SHARED_NO_READ_WRITE);
+  /* Only allow upgrade to SHARED_NO_WRITE/EXCLUSIVE */
+  DBUG_ASSERT(new_type == MDL_SHARED_NO_WRITE ||
+              new_type == MDL_EXCLUSIVE);
 
-  mdl_xlock_request.init(&mdl_ticket->m_lock->key, MDL_EXCLUSIVE,
+  mdl_xlock_request.init(&mdl_ticket->m_lock->key, new_type,
                          MDL_TRANSACTION);
 
   if (acquire_lock(&mdl_xlock_request, lock_wait_timeout))
@@ -2029,7 +2043,7 @@ MDL_context::upgrade_shared_lock_to_excl
     ticket from the granted queue and then include it back.
   */
   mdl_ticket->m_lock->m_granted.remove_ticket(mdl_ticket);
-  mdl_ticket->m_type= MDL_EXCLUSIVE;
+  mdl_ticket->m_type= new_type;
   mdl_ticket->m_lock->m_granted.add_ticket(mdl_ticket);
 
   mysql_prlock_unlock(&mdl_ticket->m_lock->m_rwlock);
@@ -2396,12 +2410,12 @@ void MDL_context::release_all_locks_for_
 
 
 /**
-  Downgrade an exclusive lock to shared metadata lock.
+  Downgrade an EXCLUSIVE or SHARED_NO_WRITE lock to shared metadata lock.
 
   @param type  Type of lock to which exclusive lock should be downgraded.
 */
 
-void MDL_ticket::downgrade_exclusive_lock(enum_mdl_type type)
+void MDL_ticket::downgrade_lock(enum_mdl_type type)
 {
   mysql_mutex_assert_not_owner(&LOCK_open);
 
@@ -2409,9 +2423,15 @@ void MDL_ticket::downgrade_exclusive_loc
     Do nothing if already downgraded. Used when we FLUSH TABLE under
     LOCK TABLES and a table is listed twice in LOCK TABLES list.
   */
-  if (m_type != MDL_EXCLUSIVE)
+  if (m_type == type)
     return;
 
+  /* Only allow downgrade from EXCLUSIVE and SHARED_NO_WRITE. */
+  DBUG_ASSERT(m_type == MDL_EXCLUSIVE ||
+              m_type == MDL_SHARED_NO_WRITE);
+  /* Check that this is really a downgrade. */
+  DBUG_ASSERT(has_stronger_or_equal_type(type));
+
   mysql_prlock_wrlock(&m_lock->m_rwlock);
   /*
     To update state of MDL_lock object correctly we need to temporarily

=== modified file 'sql/mdl.h'
--- a/sql/mdl.h	2011-07-21 16:27:14 +0000
+++ b/sql/mdl.h	2011-10-12 15:55:19 +0000
@@ -192,6 +192,15 @@ enum enum_mdl_type {
   */
   MDL_SHARED_WRITE,
   /*
+    An upgradable shared metadata lock for cases when there is an intention
+    to modify (and not just read) data in the table.
+    Can be upgraded to MDL_SHARED_NO_WRITE and MDL_EXCLUSIVE.
+    A connection holding SU lock can read table metadata and modify or read
+    table data (after acquiring appropriate table and row-level locks).
+    To be used for the first phase of ALTER TABLE.
+  */
+  MDL_SHARED_UPGRADABLE,
+  /*
     An upgradable shared metadata lock which blocks all attempts to update
     table data, allowing reads.
     A connection holding this kind of lock can read table metadata and read
@@ -562,13 +571,14 @@ public:
   MDL_context *get_ctx() const { return m_ctx; }
   bool is_upgradable_or_exclusive() const
   {
-    return m_type == MDL_SHARED_NO_WRITE ||
+    return m_type == MDL_SHARED_UPGRADABLE ||
+           m_type == MDL_SHARED_NO_WRITE ||
            m_type == MDL_SHARED_NO_READ_WRITE ||
            m_type == MDL_EXCLUSIVE;
   }
   enum_mdl_type get_type() const { return m_type; }
   MDL_lock *get_lock() const { return m_lock; }
-  void downgrade_exclusive_lock(enum_mdl_type type);
+  void downgrade_lock(enum_mdl_type type);
 
   bool has_stronger_or_equal_type(enum_mdl_type type) const;
 
@@ -720,8 +730,9 @@ public:
   bool try_acquire_lock(MDL_request *mdl_request);
   bool acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout);
   bool acquire_locks(MDL_request_list *requests, ulong lock_wait_timeout);
-  bool upgrade_shared_lock_to_exclusive(MDL_ticket *mdl_ticket,
-                                        ulong lock_wait_timeout);
+  bool upgrade_shared_lock(MDL_ticket *mdl_ticket,
+                           enum_mdl_type new_type,
+                           ulong lock_wait_timeout);
 
   bool clone_ticket(MDL_request *mdl_request);
 

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2011-09-28 10:01:37 +0000
+++ b/sql/sql_base.cc	2011-10-12 15:55:19 +0000
@@ -1227,12 +1227,12 @@ err_with_reopen:
     */
     thd->locked_tables_list.reopen_tables(thd);
     /*
-      Since downgrade_exclusive_lock() won't do anything with shared
+      Since downgrade_lock() won't do anything with shared
       metadata lock it is much simpler to go through all open tables rather
       than picking only those tables that were flushed.
     */
     for (TABLE *tab= thd->open_tables; tab; tab= tab->next)
-      tab->mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+      tab->mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
   }
   DBUG_RETURN(result);
 }
@@ -2349,8 +2349,9 @@ bool wait_while_table_is_used(THD *thd,
                        table->s->table_name.str, (ulong) table->s,
                        table->db_stat, table->s->version));
 
-  if (thd->mdl_context.upgrade_shared_lock_to_exclusive(
-             table->mdl_ticket, thd->variables.lock_wait_timeout))
+  if (thd->mdl_context.upgrade_shared_lock(
+             table->mdl_ticket, MDL_EXCLUSIVE,
+             thd->variables.lock_wait_timeout))
     DBUG_RETURN(TRUE);
 
   tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN,
@@ -3224,9 +3225,9 @@ TABLE *find_locked_table(TABLE *list, co
          upgrade the lock and ER_TABLE_NOT_LOCKED_FOR_WRITE will be
          reported.
 
-   @return Pointer to TABLE instance with MDL_SHARED_NO_WRITE,
-           MDL_SHARED_NO_READ_WRITE, or MDL_EXCLUSIVE metadata
-           lock, NULL otherwise.
+   @return Pointer to TABLE instance with MDL_SHARED_UPGRADABLE
+           MDL_SHARED_NO_WRITE, MDL_SHARED_NO_READ_WRITE, or
+           MDL_EXCLUSIVE metadata lock, NULL otherwise.
 */
 
 TABLE *find_table_for_mdl_upgrade(THD *thd, const char *db,
@@ -4739,7 +4740,7 @@ lock_table_names(THD *thd,
   for (table= tables_start; table && table != tables_end;
        table= table->next_global)
   {
-    if (table->mdl_request.type < MDL_SHARED_NO_WRITE ||
+    if (table->mdl_request.type < MDL_SHARED_UPGRADABLE ||
         table->open_type == OT_TEMPORARY_ONLY ||
         (table->open_type == OT_TEMPORARY_OR_BASE && is_temporary_table(table)))
     {
@@ -4817,7 +4818,7 @@ open_tables_check_upgradable_mdl(THD *th
   for (table= tables_start; table && table != tables_end;
        table= table->next_global)
   {
-    if (table->mdl_request.type < MDL_SHARED_NO_WRITE ||
+    if (table->mdl_request.type < MDL_SHARED_UPGRADABLE ||
         table->open_type == OT_TEMPORARY_ONLY ||
         (table->open_type == OT_TEMPORARY_OR_BASE && is_temporary_table(table)))
     {
@@ -5016,7 +5017,7 @@ restart:
       for (table= *start; table && table != thd->lex->first_not_own_table();
            table= table->next_global)
       {
-        if (table->mdl_request.type >= MDL_SHARED_NO_WRITE)
+        if (table->mdl_request.type >= MDL_SHARED_UPGRADABLE)
           table->mdl_request.ticket= NULL;
       }
     }
@@ -5562,7 +5563,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST
   table_list->required_type= FRMTYPE_TABLE;
 
   /* This function can't properly handle requests for such metadata locks. */
-  DBUG_ASSERT(table_list->mdl_request.type < MDL_SHARED_NO_WRITE);
+  DBUG_ASSERT(table_list->mdl_request.type < MDL_SHARED_UPGRADABLE);
 
   while ((error= open_table(thd, table_list, thd->mem_root, &ot_ctx)) &&
          ot_ctx.can_recover_from_failed_open())

=== modified file 'sql/sql_partition.cc'
--- a/sql/sql_partition.cc	2011-10-12 09:35:16 +0000
+++ b/sql/sql_partition.cc	2011-10-12 15:55:19 +0000
@@ -6639,7 +6639,7 @@ static void downgrade_mdl_if_lock_tables
                                               enum_mdl_type type)
 {
   if (thd->locked_tables_mode)
-    ticket->downgrade_exclusive_lock(type);
+    ticket->downgrade_lock(type);
 }
 
 

=== modified file 'sql/sql_partition_admin.cc'
--- a/sql/sql_partition_admin.cc	2011-09-13 11:15:34 +0000
+++ b/sql/sql_partition_admin.cc	2011-10-12 15:55:19 +0000
@@ -626,9 +626,9 @@ err:
   if (thd->locked_tables_mode)
   {
     if (swap_table_mdl_ticket)
-      swap_table_mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+      swap_table_mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
     if (part_table_mdl_ticket)
-      part_table_mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+      part_table_mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
   }
 
   if (!error)
@@ -760,7 +760,7 @@ bool Sql_cmd_alter_table_truncate_partit
     mandates an exclusive metadata lock.
   */
   MDL_ticket *ticket= first_table->table->mdl_ticket;
-  if (thd->mdl_context.upgrade_shared_lock_to_exclusive(ticket, timeout))
+  if (thd->mdl_context.upgrade_shared_lock(ticket, MDL_EXCLUSIVE, timeout))
     DBUG_RETURN(TRUE);
 
   tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN, first_table->db,
@@ -789,7 +789,7 @@ bool Sql_cmd_alter_table_truncate_partit
     to a shared one.
   */
   if (thd->locked_tables_mode)
-    ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+    ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
 
   if (! error)
     my_ok(thd);

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2011-10-12 09:35:16 +0000
+++ b/sql/sql_table.cc	2011-10-12 15:55:19 +0000
@@ -6139,18 +6139,20 @@ static bool mysql_inplace_alter_table(TH
 {
   DBUG_ENTER("mysql_inplace_alter_table");
 
-  create_info->options&= ~HA_LEX_CREATE_TMP_TABLE;
-  create_info->frm_only= 1;
-  if (create_altered_table(thd,
-                           db,
-                           new_db,
-                           tmp_name,
-                           create_info,
-                           alter_info))
+  /*
+    Before upgrading the metadata lock, release table level locks to
+    void deadlock. Note: Not needed under LOCK TABLES since we already
+    have a stronger lock on the table.
+  */
+  if (thd->lock &&
+      thd->locked_tables_mode != LTM_LOCK_TABLES &&
+      thd->locked_tables_mode != LTM_PRELOCKED_UNDER_LOCK_TABLES)
   {
-    DBUG_RETURN(true);
+    mysql_unlock_tables(thd, thd->lock);
+    thd->lock= NULL;
   }
 
+  // Check if we must upgrade to EXCLUSIVE before starting.
   if ((inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
        alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE) &&
       wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
@@ -6158,6 +6160,29 @@ static bool mysql_inplace_alter_table(TH
     DBUG_RETURN(true);
   }
 
+  // Check if we must upgrade to SHARED_NO_WRITE before starting.
+  if ((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK ||
+       inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE ||
+       alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED) &&
+      thd->mdl_context.upgrade_shared_lock(table->mdl_ticket,
+                                           MDL_SHARED_NO_WRITE,
+                                           thd->variables.lock_wait_timeout))
+  {
+    DBUG_RETURN(true);
+  }
+
+  // It's now safe to take the table level lock again.
+  if (!thd->lock &&
+      (!(thd->lock= mysql_lock_tables(thd, &table, 1, 0))))
+    DBUG_RETURN(true);
+
+  create_info->options&= ~HA_LEX_CREATE_TMP_TABLE;
+  create_info->frm_only= 1;
+  if (create_altered_table(thd, db, new_db, tmp_name, create_info, alter_info))
+  {
+    DBUG_RETURN(true);
+  }
+
   /* Fix the key parts. */
   for (KEY *new_key= ha_alter_info->key_info_buffer;
        new_key < ha_alter_info->key_info_buffer + ha_alter_info->key_count;
@@ -6171,6 +6196,7 @@ static bool mysql_inplace_alter_table(TH
 
   THD_STAGE_INFO(thd, stage_manage_keys);
   DEBUG_SYNC(thd, "alter_table_manage_keys");
+  // TODO: What are the locking requirements for ENABLE/DISABLE?
   alter_table_manage_keys(table, table->file->indexes_are_disabled(),
                           alter_info->keys_onoff);
   if (trans_commit_stmt(thd) || trans_commit_implicit(thd))
@@ -6185,8 +6211,6 @@ static bool mysql_inplace_alter_table(TH
   */
   table->file->ha_prepare_for_alter();
 
-  // TODO: Fix locking
-
   if (table->file->prepare_inplace_alter_table(create_info,
                                                ha_alter_info,
                                                ha_alter_flags))
@@ -6194,6 +6218,12 @@ static bool mysql_inplace_alter_table(TH
     goto rollback;
   }
 
+  // Downgrade to SHARED_UPGRADABLE if requested.
+  if (inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE &&
+      table->mdl_ticket->get_type() == MDL_SHARED_NO_WRITE &&
+      alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_SHARED)
+    table->mdl_ticket->downgrade_lock(MDL_SHARED_UPGRADABLE);
+
   if (table->file->inplace_alter_table(create_info,
                                        ha_alter_info,
                                        ha_alter_flags))
@@ -6210,6 +6240,7 @@ static bool mysql_inplace_alter_table(TH
   if (trans_commit_stmt(thd) || trans_commit_implicit(thd))
     goto rollback;
 
+  // Upgrade to EXCLUSIVE before commit.
   if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
     goto rollback;
 
@@ -6855,7 +6886,7 @@ static int simple_rename_or_index_change
     if (new_name != table_name || new_db != db)
       thd->mdl_context.release_all_locks_for_name(mdl_ticket);
     else
-      mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+      mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
   }
   DBUG_RETURN(error);
 }
@@ -7326,16 +7357,44 @@ bool mysql_alter_table(THD *thd,char *ne
 
   /* ALTER TABLE using copy algorithm. */
 
-  // If EXCLUSIVE lock is requested, upgrade already.
-  if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE &&
-      wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
-    DBUG_RETURN(true);
-
-  // COPY algorithm doesn't work with concurrent writes.
-  if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE)
+  if (!table->s->tmp_table)
   {
-    my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query());
-    DBUG_RETURN(true);
+    // COPY algorithm doesn't work with concurrent writes.
+    if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE)
+    {
+      my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query());
+      DBUG_RETURN(true);
+    }
+
+    /*
+      Before upgrading the metadata lock, release table level locks to
+      void deadlock. Note: Not needed under LOCK TABLES since we already
+      have a stronger lock on the table.
+    */
+    if (thd->lock &&
+        thd->locked_tables_mode != LTM_LOCK_TABLES &&
+        thd->locked_tables_mode != LTM_PRELOCKED_UNDER_LOCK_TABLES)
+    {
+      mysql_unlock_tables(thd, thd->lock);
+      thd->lock= NULL;
+    }
+
+    // If EXCLUSIVE lock is requested, upgrade already.
+    if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE &&
+        wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
+      DBUG_RETURN(true);
+    // Otherwise upgrade to SHARED_NO_WRITE
+    if (alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE &&
+        thd->mdl_context.upgrade_shared_lock(mdl_ticket, MDL_SHARED_NO_WRITE,
+                                             thd->variables.lock_wait_timeout))
+      DBUG_RETURN(true);
+
+    // It's now safe to take the table level lock again.
+    if (!thd->lock &&
+        (!(thd->lock= mysql_lock_tables(thd, &table, 1, 0))))
+      DBUG_RETURN(true);
+
+    DEBUG_SYNC(thd, "alter_table_copy_after_lock_upgrade");
   }
 
   if (create_altered_table(thd, db, new_db, tmp_name, create_info, alter_info))
@@ -7578,7 +7637,7 @@ end_inplace:
     if ((new_name != table_name || new_db != db))
       thd->mdl_context.release_all_locks_for_name(mdl_ticket);
     else
-      mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+      mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
   }
 
   my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),

=== modified file 'sql/sql_trigger.cc'
--- a/sql/sql_trigger.cc	2011-08-19 13:04:28 +0000
+++ b/sql/sql_trigger.cc	2011-10-12 15:55:19 +0000
@@ -589,7 +589,7 @@ end:
     with the implicit commit.
   */
   if (thd->locked_tables_mode && tables && lock_upgrade_done)
-    mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+    mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
 
   /* Restore the query table list. Used only for drop trigger. */
   if (!create)

=== modified file 'sql/sql_truncate.cc'
--- a/sql/sql_truncate.cc	2011-09-11 13:11:23 +0000
+++ b/sql/sql_truncate.cc	2011-10-12 15:55:19 +0000
@@ -489,7 +489,7 @@ bool Sql_cmd_truncate_table::truncate_ta
     to a shared one.
   */
   if (m_ticket_downgrade)
-    m_ticket_downgrade->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+    m_ticket_downgrade->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
 
   DBUG_RETURN(error);
 }

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2011-09-28 10:01:37 +0000
+++ b/sql/sql_yacc.yy	2011-10-12 15:55:19 +0000
@@ -702,8 +702,8 @@ static bool add_create_index_prepare (LE
   lex->sql_command= SQLCOM_CREATE_INDEX;
   if (!lex->current_select->add_table_to_list(lex->thd, table, NULL,
                                               TL_OPTION_UPDATING,
-                                              TL_READ_NO_INSERT,
-                                              MDL_SHARED_NO_WRITE))
+                                              TL_READ,
+                                              MDL_SHARED_UPGRADABLE))
     return TRUE;
   lex->alter_info.reset();
   lex->alter_info.flags= ALTER_ADD_INDEX;
@@ -6285,8 +6285,8 @@ alter:
             lex->duplicates= DUP_ERROR; 
             if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
                                                    TL_OPTION_UPDATING,
-                                                   TL_READ_NO_INSERT,
-                                                   MDL_SHARED_NO_WRITE))
+                                                   TL_READ,
+                                                   MDL_SHARED_UPGRADABLE))
               MYSQL_YYABORT;
             lex->col_list.empty();
             lex->select_lex.init_order();
@@ -6617,8 +6617,8 @@ alter_commands:
             lex->alter_info.flags|= ALTER_EXCHANGE_PARTITION;
             if (!lex->select_lex.add_table_to_list(thd, $6, NULL,
                                                    TL_OPTION_UPDATING,
-                                                   TL_READ_NO_INSERT,
-                                                   MDL_SHARED_NO_WRITE))
+                                                   TL_READ,
+                                                   MDL_SHARED_UPGRADABLE))
               MYSQL_YYABORT;
             DBUG_ASSERT(!lex->m_sql_cmd);
             lex->m_sql_cmd= new (thd->mem_root)
@@ -10449,8 +10449,8 @@ drop:
             lex->alter_info.drop_list.push_back(ad);
             if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
                                                         TL_OPTION_UPDATING,
-                                                        TL_READ_NO_INSERT,
-                                                        MDL_SHARED_NO_WRITE))
+                                                        TL_READ,
+                                                        MDL_SHARED_UPGRADABLE))
               MYSQL_YYABORT;
           }
         | DROP DATABASE if_exists ident

=== modified file 'storage/myisammrg/ha_myisammrg.cc'
--- a/storage/myisammrg/ha_myisammrg.cc	2011-09-21 11:01:41 +0000
+++ b/storage/myisammrg/ha_myisammrg.cc	2011-10-12 15:55:19 +0000
@@ -507,7 +507,7 @@ int ha_myisammrg::add_children_list(void
       DDL on implicitly locked underlying tables of a MERGE table.
     */
     if (! thd->locked_tables_mode &&
-        parent_l->mdl_request.type == MDL_SHARED_NO_WRITE)
+        parent_l->mdl_request.type == MDL_SHARED_UPGRADABLE)
       child_l->mdl_request.set_type(MDL_SHARED_NO_WRITE);
     /* Link TABLE_LIST object into the children list. */
     if (this->children_last_l)

=== modified file 'unittest/gunit/mdl-t.cc'
--- a/unittest/gunit/mdl-t.cc	2011-05-19 09:47:59 +0000
+++ b/unittest/gunit/mdl-t.cc	2011-10-12 15:55:19 +0000
@@ -209,7 +209,7 @@ void MDL_thread::run()
                MDL_TRANSACTION);
 
   request_list.push_front(&request);
-  if (m_mdl_type >= MDL_SHARED_NO_WRITE)
+  if (m_mdl_type >= MDL_SHARED_UPGRADABLE)
     request_list.push_front(&global_request);
 
   EXPECT_FALSE(m_mdl_context.acquire_locks(&request_list, long_timeout));
@@ -411,7 +411,7 @@ TEST_F(MDLTest, SharedLocksBetweenContex
  */
 TEST_F(MDLTest, UpgradeSharedUpgradable)
 {
-  m_request.init(MDL_key::TABLE, db_name, table_name1, MDL_SHARED_NO_WRITE,
+  m_request.init(MDL_key::TABLE, db_name, table_name1, MDL_SHARED_UPGRADABLE,
                  MDL_TRANSACTION);
 
   m_request_list.push_front(&m_request);
@@ -419,12 +419,12 @@ TEST_F(MDLTest, UpgradeSharedUpgradable)
 
   EXPECT_FALSE(m_mdl_context.acquire_locks(&m_request_list, long_timeout));
   EXPECT_FALSE(m_mdl_context.
-               upgrade_shared_lock_to_exclusive(m_request.ticket, long_timeout));
+               upgrade_shared_lock(m_request.ticket, MDL_EXCLUSIVE, long_timeout));
   EXPECT_EQ(MDL_EXCLUSIVE, m_request.ticket->get_type());
 
   // Another upgrade should be a no-op.
   EXPECT_FALSE(m_mdl_context.
-               upgrade_shared_lock_to_exclusive(m_request.ticket, long_timeout));
+               upgrade_shared_lock(m_request.ticket, MDL_EXCLUSIVE, long_timeout));
   EXPECT_EQ(MDL_EXCLUSIVE, m_request.ticket->get_type());
 
   m_mdl_context.release_transactional_locks();
@@ -451,12 +451,14 @@ TEST_F(MDLDeathTest, DieUpgradeShared)
 #if GTEST_HAS_DEATH_TEST && !defined(DBUG_OFF)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   EXPECT_DEATH_IF_SUPPORTED(m_mdl_context.
-                            upgrade_shared_lock_to_exclusive(m_request.ticket,
-                                                             long_timeout),
+                            upgrade_shared_lock(m_request.ticket,
+                                                MDL_EXCLUSIVE,
+                                                long_timeout),
                             ".*MDL_SHARED_NO_.*");
 #endif
   EXPECT_FALSE(m_mdl_context.
-               upgrade_shared_lock_to_exclusive(request_2.ticket, long_timeout));
+               upgrade_shared_lock(request_2.ticket, MDL_EXCLUSIVE,
+                                   long_timeout));
   m_mdl_context.release_transactional_locks();
 }
 
@@ -615,7 +617,7 @@ TEST_F(MDLTest, ConcurrentExclusiveShare
  */
 TEST_F(MDLTest, ConcurrentUpgrade)
 {
-  m_request.init(MDL_key::TABLE, db_name, table_name1, MDL_SHARED_NO_WRITE,
+  m_request.init(MDL_key::TABLE, db_name, table_name1, MDL_SHARED_UPGRADABLE,
                  MDL_TRANSACTION);
   m_request_list.push_front(&m_request);
   m_request_list.push_front(&m_global_request);
@@ -623,7 +625,7 @@ TEST_F(MDLTest, ConcurrentUpgrade)
   EXPECT_FALSE(m_mdl_context.acquire_locks(&m_request_list, long_timeout));
   EXPECT_TRUE(m_mdl_context.
               is_lock_owner(MDL_key::TABLE,
-                            db_name, table_name1, MDL_SHARED_NO_WRITE));
+                            db_name, table_name1, MDL_SHARED_UPGRADABLE));
   EXPECT_FALSE(m_mdl_context.
                is_lock_owner(MDL_key::TABLE,
                              db_name, table_name1, MDL_EXCLUSIVE));
@@ -635,7 +637,7 @@ TEST_F(MDLTest, ConcurrentUpgrade)
   lock_grabbed.wait_for_notification();
 
   EXPECT_FALSE(m_mdl_context.
-               upgrade_shared_lock_to_exclusive(m_request.ticket, long_timeout));
+               upgrade_shared_lock(m_request.ticket, MDL_EXCLUSIVE, long_timeout));
   EXPECT_TRUE(m_mdl_context.
               is_lock_owner(MDL_key::TABLE,
                             db_name, table_name1, MDL_EXCLUSIVE));

=== modified file 'unittest/gunit/mdl_mytap-t.cc'
--- a/unittest/gunit/mdl_mytap-t.cc	2011-05-19 09:47:59 +0000
+++ b/unittest/gunit/mdl_mytap-t.cc	2011-10-12 15:55:19 +0000
@@ -290,7 +290,7 @@ void MDL_thread::run()
                MDL_TRANSACTION);
 
   request_list.push_front(&request);
-  if (m_mdl_type >= MDL_SHARED_NO_WRITE)
+  if (m_mdl_type >= MDL_SHARED_UPGRADABLE)
     request_list.push_front(&global_request);
 
   EXPECT_FALSE(m_mdl_context.acquire_locks(&request_list, long_timeout));
@@ -477,7 +477,7 @@ TEST_F(MDLTest, SharedLocksBetweenContex
  */
 TEST_F(MDLTest, UpgradeSharedUpgradable)
 {
-  m_request.init(MDL_key::TABLE, db_name, table_name1, MDL_SHARED_NO_WRITE,
+  m_request.init(MDL_key::TABLE, db_name, table_name1, MDL_SHARED_UPGRADABLE,
                  MDL_TRANSACTION);
 
   m_request_list.push_front(&m_request);
@@ -485,12 +485,12 @@ TEST_F(MDLTest, UpgradeSharedUpgradable)
 
   EXPECT_FALSE(m_mdl_context.acquire_locks(&m_request_list, long_timeout));
   EXPECT_FALSE(m_mdl_context.
-               upgrade_shared_lock_to_exclusive(m_request.ticket, long_timeout));
+               upgrade_shared_lock(m_request.ticket, MDL_EXCLUSIVE, long_timeout));
   EXPECT_EQ(MDL_EXCLUSIVE, m_request.ticket->get_type());
 
   // Another upgrade should be a no-op.
   EXPECT_FALSE(m_mdl_context.
-               upgrade_shared_lock_to_exclusive(m_request.ticket, long_timeout));
+               upgrade_shared_lock(m_request.ticket, MDL_EXCLUSIVE, long_timeout));
   EXPECT_EQ(MDL_EXCLUSIVE, m_request.ticket->get_type());
 
   m_mdl_context.release_transactional_locks();
@@ -517,12 +517,14 @@ TEST_F(MDLDeathTest, DieUpgradeShared)
 #if GTEST_HAS_DEATH_TEST && !defined(DBUG_OFF)
   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
   EXPECT_DEATH_IF_SUPPORTED(m_mdl_context.
-                            upgrade_shared_lock_to_exclusive(m_request.ticket,
-                                                             long_timeout),
+                            upgrade_shared_lock(m_request.ticket,
+                                                MDL_EXCLUSIVE,
+                                                long_timeout),
                             ".*MDL_SHARED_NO_.*");
 #endif
   EXPECT_FALSE(m_mdl_context.
-               upgrade_shared_lock_to_exclusive(request_2.ticket, long_timeout));
+               upgrade_shared_lock(request_2.ticket, MDL_EXCLUSIVE,
+                                   long_timeout));
   m_mdl_context.release_transactional_locks();
 }
 
@@ -681,7 +683,7 @@ TEST_F(MDLTest, ConcurrentExclusiveShare
  */
 TEST_F(MDLTest, ConcurrentUpgrade)
 {
-  m_request.init(MDL_key::TABLE, db_name, table_name1, MDL_SHARED_NO_WRITE,
+  m_request.init(MDL_key::TABLE, db_name, table_name1, MDL_SHARED_UPGRADABLE,
                  MDL_TRANSACTION);
   m_request_list.push_front(&m_request);
   m_request_list.push_front(&m_global_request);
@@ -689,7 +691,7 @@ TEST_F(MDLTest, ConcurrentUpgrade)
   EXPECT_FALSE(m_mdl_context.acquire_locks(&m_request_list, long_timeout));
   EXPECT_TRUE(m_mdl_context.
               is_lock_owner(MDL_key::TABLE,
-                            db_name, table_name1, MDL_SHARED_NO_WRITE));
+                            db_name, table_name1, MDL_SHARED_UPGRADABLE));
   EXPECT_FALSE(m_mdl_context.
                is_lock_owner(MDL_key::TABLE,
                              db_name, table_name1, MDL_EXCLUSIVE));
@@ -701,7 +703,8 @@ TEST_F(MDLTest, ConcurrentUpgrade)
   lock_grabbed.wait_for_notification();
 
   EXPECT_FALSE(m_mdl_context.
-               upgrade_shared_lock_to_exclusive(m_request.ticket, long_timeout));
+               upgrade_shared_lock(m_request.ticket, MDL_EXCLUSIVE,
+                                   long_timeout));
   EXPECT_TRUE(m_mdl_context.
               is_lock_owner(MDL_key::TABLE,
                             db_name, table_name1, MDL_EXCLUSIVE));

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-wl5534 branch (jon.hauglid:3403 to 3404) WL#5534Jon Olav Hauglid13 Oct