List:Commits« Previous MessageNext Message »
From:Jon Olav Hauglid Date:September 17 2010 8:48am
Subject:bzr commit into mysql-5.5-runtime branch (jon.hauglid:3141) Bug#56422
Bug#56494
View as plain text  
#At file:///export/home/x/mysql-5.5-runtime-bug56494/ based on revid:jon.hauglid@stripped

 3141 Jon Olav Hauglid	2010-09-17
      Bug #56494 Segfault in upgrade_shared_lock_to_exclusive() for
                 REPAIR of merge table
      Bug #56422 CHECK TABLE run when the table is locked reports
                 corruption along with timeout
      
      The crash happened if a table maintenance statement (ANALYZE TABLE,
      REPAIR TABLE, etc.) was executed on a MERGE table and opening and 
      locking a child table failed. This could for example happen if a child
      table did not exist or if a lock timeout happened while waiting for
      a conflicting metadata lock to disappear.
      
      Since opening and locking the MERGE table and its children failed,
      the tables would be closed and the metadata locks released.
      However, TABLE_LIST::table for the MERGE table would still be set,
      with its value invalid since the tables had been closed.
      This caused the table maintenance statement to try to continue
      and upgrade the metadata lock on the MERGE table. But since the lock
      already had been released, this caused a segfault.
      
      This patch fixes the problem by setting TABLE_LIST::table to NULL 
      if open_and_lock_tables() fails. This prevents the maintenance
      statement from continuing and trying to upgrade the metadata lock.
      
      The patch also fixes a problem where REPAIR TABLE ... USE_FRM
      would cause an assert for MERGE tables, even if child tables
      were opened successfully.
      
      Finally, the patch changes the error message from "Corrupt" to
      "Operation failed" for a number of issues not related to table
      corruption. For example "Lock wait timeout exceeded" and 
      "Deadlock found trying to get lock".
      
      Test cases added to mdl_sync.test and check.test.

    modified:
      mysql-test/r/check.result
      mysql-test/r/log_tables_upgrade.result
      mysql-test/r/mdl_sync.result
      mysql-test/r/merge.result
      mysql-test/r/myisampack.result
      mysql-test/r/mysql_upgrade.result
      mysql-test/r/mysql_upgrade_ssl.result
      mysql-test/t/check.test
      mysql-test/t/mdl_sync.test
      sql/sql_admin.cc
=== modified file 'mysql-test/r/check.result'
--- a/mysql-test/r/check.result	2009-02-09 21:00:15 +0000
+++ b/mysql-test/r/check.result	2010-09-17 08:48:32 +0000
@@ -23,3 +23,19 @@ REPAIR TABLE t1;
 Table	Op	Msg_type	Msg_text
 test.t1	repair	status	OK
 DROP TABLE t1;
+#
+# Bug#56422 CHECK TABLE run when the table is locked reports corruption
+#           along with timeout
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(a INT);
+LOCK TABLE t1 WRITE;
+# Connection con1
+SET lock_wait_timeout= 1;
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	Error	Lock wait timeout exceeded; try restarting transaction
+test.t1	check	status	Operation failed
+# Connection default
+UNLOCK TABLES;
+DROP TABLE t1;

=== modified file 'mysql-test/r/log_tables_upgrade.result'
--- a/mysql-test/r/log_tables_upgrade.result	2010-02-26 12:22:48 +0000
+++ b/mysql-test/r/log_tables_upgrade.result	2010-09-17 08:48:32 +0000
@@ -19,7 +19,7 @@ mysql.event                             
 mysql.func                                         OK
 mysql.general_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -33,7 +33,7 @@ mysql.renamed_general_log               
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -41,6 +41,10 @@ mysql.time_zone_name                    
 mysql.time_zone_transition                         OK
 mysql.time_zone_transition_type                    OK
 mysql.user                                         OK
+
+Repairing tables
+mysql.general_log                                  OK
+mysql.slow_log                                     OK
 DROP TABLE general_log;
 RENAME TABLE renamed_general_log TO general_log;
 SET GLOBAL general_log = @saved_general_log;

=== modified file 'mysql-test/r/mdl_sync.result'
--- a/mysql-test/r/mdl_sync.result	2010-09-08 08:25:37 +0000
+++ b/mysql-test/r/mdl_sync.result	2010-09-17 08:48:32 +0000
@@ -2951,3 +2951,47 @@ SET DEBUG_SYNC= 'now SIGNAL continue';
 # Connection default
 DROP TABLE m1, t1, t2;
 SET DEBUG_SYNC= 'RESET';
+#
+# Bug#56494 Segfault in upgrade_shared_lock_to_exclusive() for
+#           REPAIR of merge table
+#
+DROP TABLE IF EXISTS t1, t2, t_not_exists;
+CREATE TABLE t1(a INT);
+ALTER TABLE t1 engine= MERGE UNION (t_not_exists);
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	Error	Table 'test.t_not_exists' doesn't exist
+test.t1	analyze	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1	analyze	status	Operation failed
+CHECK TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	check	Error	Table 'test.t_not_exists' doesn't exist
+test.t1	check	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1	check	status	Operation failed
+CHECKSUM TABLE t1;
+Table	Checksum
+test.t1	NULL
+Warnings:
+Error	1146	Table 'test.t_not_exists' doesn't exist
+Error	1168	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+OPTIMIZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	optimize	Error	Table 'test.t_not_exists' doesn't exist
+test.t1	optimize	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1	optimize	status	Operation failed
+REPAIR TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	Error	Table 'test.t_not_exists' doesn't exist
+test.t1	repair	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
+test.t1	repair	status	Operation failed
+REPAIR TABLE t1 USE_FRM;
+Table	Op	Msg_type	Msg_text
+test.t1	repair	Warning	Can't open table
+test.t1	repair	status	Operation failed
+DROP TABLE t1;
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(a INT) engine= MERGE UNION (t1);
+REPAIR TABLE t2 USE_FRM;
+Table	Op	Msg_type	Msg_text
+test.t2	repair	note	The storage engine for the table doesn't support repair
+DROP TABLE t1, t2;

=== modified file 'mysql-test/r/merge.result'
--- a/mysql-test/r/merge.result	2010-09-16 14:06:46 +0000
+++ b/mysql-test/r/merge.result	2010-09-17 08:48:32 +0000
@@ -906,7 +906,7 @@ CHECK TABLE tm1;
 Table	Op	Msg_type	Msg_text
 test.tm1	check	Error	Table 'test.t1' doesn't exist
 test.tm1	check	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
-test.tm1	check	error	Corrupt
+test.tm1	check	status	Operation failed
 CREATE TABLE t1(a INT);
 SELECT * FROM tm1;
 ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
@@ -914,7 +914,7 @@ CHECK TABLE tm1;
 Table	Op	Msg_type	Msg_text
 test.tm1	check	Error	Table 'test.t2' doesn't exist
 test.tm1	check	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
-test.tm1	check	error	Corrupt
+test.tm1	check	status	Operation failed
 CREATE TABLE t2(a BLOB);
 SELECT * FROM tm1;
 ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
@@ -922,7 +922,7 @@ CHECK TABLE tm1;
 Table	Op	Msg_type	Msg_text
 test.tm1	check	Warning	Table 'test.t2' is differently defined or of non-MyISAM type or doesn't exist
 test.tm1	check	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
-test.tm1	check	error	Corrupt
+test.tm1	check	status	Operation failed
 ALTER TABLE t2 MODIFY a INT;
 SELECT * FROM tm1;
 a
@@ -2677,7 +2677,7 @@ OPTIMIZE TABLE t1;
 Table	Op	Msg_type	Msg_text
 test.t1	optimize	Error	Table 'test.t_not_exists' doesn't exist
 test.t1	optimize	Error	Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist
-test.t1	optimize	note	The storage engine for the table doesn't support optimize
+test.t1	optimize	status	Operation failed
 DROP TABLE t1;
 #
 # Bug#36171 - CREATE TEMPORARY TABLE and MERGE engine

=== modified file 'mysql-test/r/myisampack.result'
--- a/mysql-test/r/myisampack.result	2009-11-26 12:47:55 +0000
+++ b/mysql-test/r/myisampack.result	2010-09-17 08:48:32 +0000
@@ -46,14 +46,12 @@ insert into t1 select * from t1;
 flush tables;
 optimize table t1;
 Table	Op	Msg_type	Msg_text
-test.t1	optimize	error	Table 'test.t1' is read only
-Warnings:
-Error	1036	Table 't1' is read only
+test.t1	optimize	Error	Table 't1' is read only
+test.t1	optimize	status	Operation failed
 repair table t1;
 Table	Op	Msg_type	Msg_text
-test.t1	repair	error	Table 'test.t1' is read only
-Warnings:
-Error	1036	Table 't1' is read only
+test.t1	repair	Error	Table 't1' is read only
+test.t1	repair	status	Operation failed
 drop table t1;
 #
 # BUG#41541 - Valgrind warnings on packed MyISAM table

=== modified file 'mysql-test/r/mysql_upgrade.result'
--- a/mysql-test/r/mysql_upgrade.result	2010-07-05 10:22:13 +0000
+++ b/mysql-test/r/mysql_upgrade.result	2010-09-17 08:48:32 +0000
@@ -7,7 +7,7 @@ mysql.event                             
 mysql.func                                         OK
 mysql.general_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -20,7 +20,7 @@ mysql.procs_priv                        
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -28,6 +28,10 @@ mysql.time_zone_name                    
 mysql.time_zone_transition                         OK
 mysql.time_zone_transition_type                    OK
 mysql.user                                         OK
+
+Repairing tables
+mysql.general_log                                  OK
+mysql.slow_log                                     OK
 Run it again - should say already completed
 This installation of MySQL is already upgraded to VERSION, use --force if you still need to run mysql_upgrade
 Force should run it regardless of wether it's been run before
@@ -39,7 +43,7 @@ mysql.event                             
 mysql.func                                         OK
 mysql.general_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -52,7 +56,7 @@ mysql.procs_priv                        
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -60,6 +64,10 @@ mysql.time_zone_name                    
 mysql.time_zone_transition                         OK
 mysql.time_zone_transition_type                    OK
 mysql.user                                         OK
+
+Repairing tables
+mysql.general_log                                  OK
+mysql.slow_log                                     OK
 CREATE USER mysqltest1@'%' IDENTIFIED by 'sakila';
 GRANT ALL ON *.* TO mysqltest1@'%';
 Run mysql_upgrade with password protected account
@@ -71,7 +79,7 @@ mysql.event                             
 mysql.func                                         OK
 mysql.general_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -84,7 +92,7 @@ mysql.procs_priv                        
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -92,6 +100,10 @@ mysql.time_zone_name                    
 mysql.time_zone_transition                         OK
 mysql.time_zone_transition_type                    OK
 mysql.user                                         OK
+
+Repairing tables
+mysql.general_log                                  OK
+mysql.slow_log                                     OK
 DROP USER mysqltest1@'%';
 Run mysql_upgrade with a non existing server socket
 mysqlcheck: Got error: 2005: Unknown MySQL server host 'not_existing_host' (errno) when trying to connect
@@ -105,7 +117,7 @@ mysql.event                             
 mysql.func                                         OK
 mysql.general_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -118,7 +130,7 @@ mysql.procs_priv                        
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -126,6 +138,10 @@ mysql.time_zone_name                    
 mysql.time_zone_transition                         OK
 mysql.time_zone_transition_type                    OK
 mysql.user                                         OK
+
+Repairing tables
+mysql.general_log                                  OK
+mysql.slow_log                                     OK
 set GLOBAL sql_mode=default;
 #
 # Bug #41569 mysql_upgrade (ver 5.1) add 3 fields to mysql.proc table 
@@ -143,7 +159,7 @@ mysql.event                             
 mysql.func                                         OK
 mysql.general_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -156,7 +172,7 @@ mysql.procs_priv                        
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -164,6 +180,10 @@ mysql.time_zone_name                    
 mysql.time_zone_transition                         OK
 mysql.time_zone_transition_type                    OK
 mysql.user                                         OK
+
+Repairing tables
+mysql.general_log                                  OK
+mysql.slow_log                                     OK
 CALL testproc();
 DROP PROCEDURE testproc;
 WARNING: NULL values of the 'character_set_client' column ('mysql.proc' table) have been updated with a default value (latin1). Please verify if necessary.
@@ -184,7 +204,7 @@ mysql.event                             
 mysql.func                                         OK
 mysql.general_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -197,7 +217,7 @@ mysql.procs_priv                        
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -205,6 +225,10 @@ mysql.time_zone_name                    
 mysql.time_zone_transition                         OK
 mysql.time_zone_transition_type                    OK
 mysql.user                                         OK
+
+Repairing tables
+mysql.general_log                                  OK
+mysql.slow_log                                     OK
 SHOW GRANTS FOR 'user3'@'%';
 Grants for user3@%
 GRANT USAGE ON *.* TO 'user3'@'%'

=== modified file 'mysql-test/r/mysql_upgrade_ssl.result'
--- a/mysql-test/r/mysql_upgrade_ssl.result	2010-08-11 17:56:56 +0000
+++ b/mysql-test/r/mysql_upgrade_ssl.result	2010-09-17 08:48:32 +0000
@@ -9,7 +9,7 @@ mysql.event                             
 mysql.func                                         OK
 mysql.general_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.help_category                                OK
 mysql.help_keyword                                 OK
 mysql.help_relation                                OK
@@ -22,7 +22,7 @@ mysql.procs_priv                        
 mysql.servers                                      OK
 mysql.slow_log
 Error    : You can't use locks with log tables.
-status   : OK
+status   : Operation failed
 mysql.tables_priv                                  OK
 mysql.time_zone                                    OK
 mysql.time_zone_leap_second                        OK
@@ -30,3 +30,7 @@ mysql.time_zone_name                    
 mysql.time_zone_transition                         OK
 mysql.time_zone_transition_type                    OK
 mysql.user                                         OK
+
+Repairing tables
+mysql.general_log                                  OK
+mysql.slow_log                                     OK

=== modified file 'mysql-test/t/check.test'
--- a/mysql-test/t/check.test	2009-02-09 21:00:15 +0000
+++ b/mysql-test/t/check.test	2010-09-17 08:48:32 +0000
@@ -53,5 +53,29 @@ REPAIR TABLE t1;
 DROP TABLE t1;
 
 
+--echo #
+--echo # Bug#56422 CHECK TABLE run when the table is locked reports corruption
+--echo #           along with timeout
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1(a INT);
+LOCK TABLE t1 WRITE;
+
+--echo # Connection con1
+connect(con1, localhost, root);
+SET lock_wait_timeout= 1;
+CHECK TABLE t1;
+
+--echo # Connection default
+connection default;
+UNLOCK TABLES;
+DROP TABLE t1;
+disconnect con1;
+
+
 # Wait till we reached the initial number of concurrent sessions
 --source include/wait_until_count_sessions.inc

=== modified file 'mysql-test/t/mdl_sync.test'
--- a/mysql-test/t/mdl_sync.test	2010-09-08 08:25:37 +0000
+++ b/mysql-test/t/mdl_sync.test	2010-09-17 08:48:32 +0000
@@ -4594,6 +4594,36 @@ disconnect con1;
 disconnect con2;
 
 
+--echo #
+--echo # Bug#56494 Segfault in upgrade_shared_lock_to_exclusive() for
+--echo #           REPAIR of merge table
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2, t_not_exists;
+--enable_warnings
+
+CREATE TABLE t1(a INT);
+ALTER TABLE t1 engine= MERGE UNION (t_not_exists);
+# This caused the segfault
+ANALYZE TABLE t1;
+CHECK TABLE t1;
+CHECKSUM TABLE t1;
+OPTIMIZE TABLE t1;
+REPAIR TABLE t1;
+
+# This caused an assert
+REPAIR TABLE t1 USE_FRM;
+
+DROP TABLE t1;
+CREATE TABLE t1(a INT);
+CREATE TABLE t2(a INT) engine= MERGE UNION (t1);
+# This caused an assert
+REPAIR TABLE t2 USE_FRM;
+
+DROP TABLE t1, t2;
+
+
 # Check that all connections opened by test cases in this file are really
 # gone so execution of other tests won't be affected by their presence.
 --source include/wait_until_count_sessions.inc

=== modified file 'sql/sql_admin.cc'
--- a/sql/sql_admin.cc	2010-08-18 11:29:04 +0000
+++ b/sql/sql_admin.cc	2010-09-17 08:48:32 +0000
@@ -112,7 +112,8 @@ static int prepare_for_repair(THD *thd, 
   }
 
   /* A MERGE table must not come here. */
-  DBUG_ASSERT(table->file->ht->db_type != DB_TYPE_MRG_MYISAM);
+  if (table->file->ht->db_type == DB_TYPE_MRG_MYISAM)
+    goto end;
 
   /*
     REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
@@ -231,6 +232,27 @@ end:
 }
 
 
+/**
+  Check if a given error is something that could occur during
+  open_and_lock_tables() that does not indicate table corruption.
+
+  @param  sql_errno  Error number to check.
+
+  @retval TRUE       Error does not indicate table corruption.
+  @retval FALSE      Error could indicate table corruption.
+*/
+
+static inline bool table_not_corrupt_error(uint sql_errno)
+{
+  return (sql_errno == ER_NO_SUCH_TABLE ||
+          sql_errno == ER_FILE_NOT_FOUND ||
+          sql_errno == ER_LOCK_WAIT_TIMEOUT ||
+          sql_errno == ER_LOCK_DEADLOCK ||
+          sql_errno == ER_CANT_LOCK_LOG_TABLE ||
+          sql_errno == ER_WRONG_MRG_TABLE ||
+          sql_errno == ER_OPEN_AS_READONLY);
+}
+
 
 /*
   RETURN VALUES
@@ -320,6 +342,14 @@ static bool mysql_admin_table(THD* thd, 
       table->next_global= save_next_global;
       table->next_local= save_next_local;
       thd->open_options&= ~extra_open_options;
+
+      /*
+        If open_and_lock_tables() failed, close_thread_tables() will close
+        the table and table->table can therefore be invalid.
+      */
+      if (open_error)
+        table->table= NULL;
+
       /*
         Under locked tables, we know that the table can be opened,
         so any errors opening the table are logical errors.
@@ -418,9 +448,7 @@ static bool mysql_admin_table(THD* thd, 
         push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                      ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
       if (thd->stmt_da->is_error() &&
-          (thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE ||
-           thd->stmt_da->sql_errno() == ER_FILE_NOT_FOUND))
-        /* A missing table is just issued as a failed command */
+          table_not_corrupt_error(thd->stmt_da->sql_errno()))
         result_code= HA_ADMIN_FAILED;
       else
         /* Default failure code is corrupt table */


Attachment: [text/bzr-bundle] bzr/jon.hauglid@oracle.com-20100917084832-oz1iqblxirosh57y.bundle
Thread
bzr commit into mysql-5.5-runtime branch (jon.hauglid:3141) Bug#56422Bug#56494Jon Olav Hauglid17 Sep