List:Commits« Previous MessageNext Message »
From:Dmitry Lenev Date:November 19 2010 7:27am
Subject:bzr push into mysql-5.5-runtime branch (Dmitry.Lenev:3192 to 3193) Bug#57985
View as plain text  
 3193 Dmitry Lenev	2010-11-19
      Fix for bug #57985 "ONLINE/FAST ALTER PARTITION can fail and 
      leave the table unusable".
       
      Failing ALTER statement on partitioned table could have left
      this table in an unusable state. This has happened in cases
      when ALTER was executed using "fast" algorithm, which doesn't 
      involve copying of data between old and new versions of table, 
      and the resulting new table was incompatible with partitioning
      function in some way.
       
      The problem stems from the fact that discrepancies between new 
      table definition and partitioning function are discovered only 
      when the table is opened. In case of "fast" algorithm this has
      happened too late during ALTER's execution, at the moment when
      all changes were already done and couldn't have been reverted.
       
      In the cases when "slow" algorithm, which copies data, is used 
      such discrepancies are detected at the moment new table
      definition is opened implicitly when new version of table is
      created in storage engine. As result ALTER is aborted before 
      any changes to table were done.
       
      This fix tries to address this issue by ensuring that "fast"
      algorithm behaves similarly to "slow" algorithm and checks
      compatibility between new definition and partitioning function 
      by trying to open new definition after .FRM file for it has 
      been created.
       
      Long term we probably should implement some way to check
      compatibility between partitioning function and new table
      definition which won't involve opening it, as this should
      allow much cleaner fix for this problem.
     @ mysql-test/r/partition_innodb.result
        Added test for bug #57985 "ONLINE/FAST ALTER PARTITION can
        fail and leave the table unusable".
     @ mysql-test/t/partition_innodb.test
        Added test for bug #57985 "ONLINE/FAST ALTER PARTITION can
        fail and leave the table unusable".
     @ sql/sql_table.cc
        Ensure that in cases when .FRM for partitioned table is
        created without creating table in storage engine (e.g.
        during "fast" ALTER TABLE) we still open table definition. 
        This allows to check that definition of created table/.FRM 
        is compatible with its partitioning function.

    modified:
      mysql-test/r/partition_innodb.result
      mysql-test/t/partition_innodb.test
      sql/sql_table.cc
 3192 Jon Olav Hauglid	2010-11-18 [merge]
      Merge from mysql-5.5-bugteam to mysql-5.5-runtime
      No conflicts

    removed:
      mysql-test/suite/innodb/r/innodb_bug54679.result
      mysql-test/suite/innodb/r/innodb_bug56632.result
      mysql-test/suite/innodb/t/innodb_bug54679.test
      mysql-test/suite/innodb/t/innodb_bug56632.test
    added:
      mysql-test/suite/innodb/r/innodb-create-options.result
      mysql-test/suite/innodb/r/innodb_bug53046.result
      mysql-test/suite/innodb/r/innodb_bug57904.result
      mysql-test/suite/innodb/t/innodb-create-options.test
      mysql-test/suite/innodb/t/innodb_bug53046.test
      mysql-test/suite/innodb/t/innodb_bug57904.test
    modified:
      mysql-test/r/show_check.result
      mysql-test/r/xml.result
      mysql-test/suite/innodb/r/innodb-zip.result
      mysql-test/suite/innodb/t/innodb-zip.test
      mysql-test/t/show_check.test
      mysql-test/t/xml.test
      sql/event_data_objects.cc
      sql/item.cc
      sql/log_event.cc
      sql/slave.cc
      sql/sp_head.cc
      sql/sql_acl.cc
      sql/sql_audit.h
      sql/sql_class.cc
      sql/sql_class.h
      sql/sql_insert.cc
      sql/sql_parse.cc
      sql/sql_prepare.cc
      sql/sql_show.cc
      storage/innobase/btr/btr0cur.c
      storage/innobase/dict/dict0crea.c
      storage/innobase/dict/dict0dict.c
      storage/innobase/dict/dict0load.c
      storage/innobase/fil/fil0fil.c
      storage/innobase/fsp/fsp0fsp.c
      storage/innobase/handler/ha_innodb.cc
      storage/innobase/handler/handler0alter.cc
      storage/innobase/include/btr0btr.h
      storage/innobase/include/btr0btr.ic
      storage/innobase/include/btr0cur.h
      storage/innobase/include/db0err.h
      storage/innobase/include/dict0dict.h
      storage/innobase/include/fil0fil.h
      storage/innobase/include/row0ins.h
      storage/innobase/include/row0upd.h
      storage/innobase/include/univ.i
      storage/innobase/row/row0ins.c
      storage/innobase/row/row0merge.c
      storage/innobase/row/row0mysql.c
      storage/innobase/row/row0sel.c
      storage/innobase/row/row0upd.c
      storage/innobase/sync/sync0rw.c
      storage/innobase/thr/thr0loc.c
      storage/innobase/trx/trx0i_s.c
      storage/innobase/ut/ut0ut.c
      storage/myisam/ha_myisam.cc
=== modified file 'mysql-test/r/partition_innodb.result'
--- a/mysql-test/r/partition_innodb.result	2010-09-13 13:56:56 +0000
+++ b/mysql-test/r/partition_innodb.result	2010-11-19 07:26:09 +0000
@@ -489,3 +489,31 @@ Warning	1265	Data truncated for column '
 Error	1067	Invalid default value for 'b'
 SET SESSION sql_mode = @old_mode;
 DROP TABLE t1;
+#
+# Bug#57985 "ONLINE/FAST ALTER PARTITION can fail and leave the
+#            table unusable".
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a bigint not null, b int not null, PRIMARY KEY (a))
+ENGINE = InnoDB PARTITION BY KEY(a) PARTITIONS 2;
+INSERT INTO t1 values (0,1), (1,2);
+# The below ALTER should fail. It should leave the
+# table in its original, non-corrupted, usable state.
+ALTER TABLE t1 ADD UNIQUE KEY (b);
+ERROR HY000: A UNIQUE INDEX must include all columns in the table's partitioning function
+# The below statements should succeed, as ALTER should
+# have left table intact.
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` bigint(20) NOT NULL,
+  `b` int(11) NOT NULL,
+  PRIMARY KEY (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY KEY (a)
+PARTITIONS 2 */
+SELECT * FROM t1;
+a	b
+1	2
+0	1
+DROP TABLE t1;

=== modified file 'mysql-test/t/partition_innodb.test'
--- a/mysql-test/t/partition_innodb.test	2010-08-20 17:15:48 +0000
+++ b/mysql-test/t/partition_innodb.test	2010-11-19 07:26:09 +0000
@@ -569,3 +569,24 @@ SET SESSION sql_mode = 'NO_ZERO_DATE';
 OPTIMIZE TABLE t1;
 SET SESSION sql_mode = @old_mode;
 DROP TABLE t1;
+
+
+--echo #
+--echo # Bug#57985 "ONLINE/FAST ALTER PARTITION can fail and leave the
+--echo #            table unusable".
+--echo #
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+CREATE TABLE t1 (a bigint not null, b int not null, PRIMARY KEY (a))
+  ENGINE = InnoDB PARTITION BY KEY(a) PARTITIONS 2;
+INSERT INTO t1 values (0,1), (1,2);
+--echo # The below ALTER should fail. It should leave the
+--echo # table in its original, non-corrupted, usable state.
+--error ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF
+ALTER TABLE t1 ADD UNIQUE KEY (b);
+--echo # The below statements should succeed, as ALTER should
+--echo # have left table intact.
+SHOW CREATE TABLE t1;
+SELECT * FROM t1;
+DROP TABLE t1;

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2010-11-16 10:00:12 +0000
+++ b/sql/sql_table.cc	2010-11-19 07:26:09 +0000
@@ -3815,6 +3815,46 @@ void sp_prepare_create_field(THD *thd, C
   (void) prepare_blob_field(thd, sql_field);
 }
 
+
+/**
+  Auxiliary function which allows to check if freshly created .FRM
+  file for table can be opened.
+
+  @retval FALSE - Success.
+  @retval TRUE  - Failure.
+*/
+
+static bool check_if_created_table_can_be_opened(THD *thd,
+                                                 const char *path,
+                                                 const char *db,
+                                                 const char *table_name,
+                                                 HA_CREATE_INFO *create_info,
+                                                 handler *file)
+{
+  TABLE table;
+  TABLE_SHARE share;
+  bool result;
+
+  /*
+    It is impossible to open definition of partitioned table without .par file.
+  */
+  if (file->ha_create_handler_files(path, NULL, CHF_CREATE_FLAG, create_info))
+    return TRUE;
+
+  init_tmp_table_share(thd, &share, db, 0, table_name, path);
+
+  result= (open_table_def(thd, &share, 0) ||
+           open_table_from_share(thd, &share, "", 0, (uint) READ_ALL,
+                                 0, &table, TRUE));
+  if (! result)
+    (void) closefrm(&table, 0);
+
+  free_table_share(&share);
+  (void) file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, create_info);
+  return result;
+}
+
+
 /*
   Create a table
 
@@ -4241,6 +4281,29 @@ bool mysql_create_table_no_lock(THD *thd
 
     thd->thread_specific_used= TRUE;
   }
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+  else if (part_info && create_info->frm_only)
+  {
+    /*
+      For partitioned tables we can't find some problems with table
+      until table is opened. Therefore in order to disallow creation
+      of corrupted tables we have to try to open table as the part
+      of its creation process.
+      In cases when both .FRM and SE part of table are created table
+      is implicitly open in ha_create_table() call.
+      In cases when we create .FRM without SE part we have to open
+      table explicitly.
+    */
+    if (check_if_created_table_can_be_opened(thd, path, db, table_name,
+                                             create_info, file))
+    {
+      char frm_name[FN_REFLEN];
+      strxmov(frm_name, path, reg_ext, NullS);
+      (void) mysql_file_delete(key_file_frm, frm_name, MYF(0));
+      goto err;
+    }
+  }
+#endif
 
   error= FALSE;
 err:

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.5-runtime branch (Dmitry.Lenev:3192 to 3193) Bug#57985Dmitry Lenev19 Nov