List:Commits« Previous MessageNext Message »
From:Magne Mahre Date:October 19 2010 10:27am
Subject:bzr commit into mysql-5.1-bugteam branch (magne.mahre:3536) Bug#46941
View as plain text  
#At file:///export/home/tmp/x/mysql-5.1-bugteam-46941/ based on revid:jon.hauglid@stripped

 3536 Magne Mahre	2010-10-19
      Bug #46941 crash with lower_case_table_names=2 and foreign key 
                 data dictionary confusion
      
      On file systems with case insensitive file names, and
      lower_case_table_names set to '2', the server could crash
      due to a table definition cache inconsistency.  This is 
      the default setting on MacOSX, but may also be set and
      used on MS Windows.
      
      The bug is caused by using two different strategies for
      creating the hash key for the table definition cache, resulting
      in failure to look up an entry which is present in the cache,
      or failure to delete an existing entry.  One strategy was to
      use the real table name (with case preserved), and the other
      to use a normalized table name (i.e a lower case version).
      
      This is manifested in two cases.  One is  during 'DROP DATABASE', 
      where all known files are removed.  The removal from
      the table definition cache is done via a generated list of
      TABLE_LIST with keys (wrongly) created using the case preserved 
      name.  The other is during CREATE TABLE, where the cache lookup
      is also (wrongly) based on the case preserved name.
         
      The fix was to use only the normalized table name when
      creating hash keys.
     @ sql/sql_db.cc
        Normalize table name (i.e lower case it)
     @ sql/sql_table.cc
        table_name contains the normalized name
        alias contains the real table name

    added:
      mysql-test/r/lowercase_table4.result
      mysql-test/t/lowercase_table4-master.opt
      mysql-test/t/lowercase_table4.test
    modified:
      sql/sql_db.cc
      sql/sql_table.cc
=== added file 'mysql-test/r/lowercase_table4.result'
--- a/mysql-test/r/lowercase_table4.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/lowercase_table4.result	2010-10-19 10:27:09 +0000
@@ -0,0 +1,7 @@
+#
+# Bug#46941 crash with lower_case_table_names=2 and
+#           foreign data dictionary confusion
+#
+CREATE DATABASE XY;
+USE XY;
+DROP DATABASE XY;

=== added file 'mysql-test/t/lowercase_table4-master.opt'
--- a/mysql-test/t/lowercase_table4-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/lowercase_table4-master.opt	2010-10-19 10:27:09 +0000
@@ -0,0 +1 @@
+--lower-case-table-names=2

=== added file 'mysql-test/t/lowercase_table4.test'
--- a/mysql-test/t/lowercase_table4.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/lowercase_table4.test	2010-10-19 10:27:09 +0000
@@ -0,0 +1,56 @@
+--source include/have_case_insensitive_file_system.inc
+--source include/have_innodb.inc
+
+--echo #
+--echo # Bug#46941 crash with lower_case_table_names=2 and
+--echo #           foreign data dictionary confusion
+--echo #
+
+CREATE DATABASE XY;
+USE XY;
+
+#
+# Logs are disabled, since the number of creates tables
+# and subsequent select statements may vary between
+# versions
+#
+--disable_query_log
+--disable_result_log
+
+let $tcs = `SELECT @@table_open_cache + 1`;
+
+let $i = $tcs;
+
+while ($i)
+{
+  eval CREATE TABLE XY.T_$i (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, 
+                             primary key(a, b), unique(b)) ENGINE=InnoDB;
+  dec $i;
+}
+
+eval ALTER TABLE XY.T_$tcs ADD INDEX I1 (c, b), 
+                           ADD CONSTRAINT C1 FOREIGN KEY (c, b) REFERENCES XY.T_1 (a, b);
+                   
+eval ALTER TABLE XY.T_$tcs ADD INDEX I2 (b),
+                           ADD CONSTRAINT C2 FOREIGN KEY (b) REFERENCES XY.T_1(a);
+ 
+let $i = $tcs;
+while ($i)
+{
+  eval SELECT * FROM XY.T_$i LIMIT 1;
+  dec $i;
+}
+
+DROP DATABASE XY;
+CREATE DATABASE XY;
+USE XY;
+eval CREATE TABLE XY.T_$tcs (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, 
+                             PRIMARY KEY(a, b), UNIQUE(b)) ENGINE=InnoDB;
+#
+# The bug causes this SELECT to err
+eval SELECT * FROM XY.T_$tcs LIMIT 1;
+
+--enable_query_log
+--enable_result_log
+DROP DATABASE XY;
+

=== modified file 'sql/sql_db.cc'
--- a/sql/sql_db.cc	2010-06-26 17:36:00 +0000
+++ b/sql/sql_db.cc	2010-10-19 10:27:09 +0000
@@ -1197,6 +1197,12 @@ static long mysql_rm_known_files(THD *th
       VOID(filename_to_tablename(file->name, table_list->table_name,
                                  MYSQL50_TABLE_NAME_PREFIX_LENGTH +
                                  strlen(file->name) + 1));
+
+      /* To be able to correctly look up the table in the table cache. */
+      if (lower_case_table_names)
+        table_list->table_name_length= my_casedn_str(files_charset_info,
+                                                     table_list->table_name);
+
       table_list->alias= table_list->table_name;	// If lower_case_table_names=2
       table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix);
       /* Link into list */

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2010-09-21 14:37:18 +0000
+++ b/sql/sql_table.cc	2010-10-19 10:27:09 +0000
@@ -3896,7 +3896,7 @@ bool mysql_create_table_no_lock(THD *thd
       Then she could create the table. This case is pretty obscure and
       therefore we don't introduce a new error message only for it.
     */
-    if (get_cached_table_share(db, alias))
+    if (get_cached_table_share(db, table_name))
     {
       my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
       goto unlock_and_end;


Attachment: [text/bzr-bundle] bzr/magne.mahre@sun.com-20101019102709-3xcmv9xauuuxu80s.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (magne.mahre:3536) Bug#46941Magne Mahre19 Oct