List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:February 5 2010 1:01pm
Subject:bzr push into mysql-5.1-bugteam branch (joro:3363 to 3364) Bug#39022
View as plain text  
 3364 Georgi Kodinov	2009-12-23
      Bug #39022: Mysql randomly crashing in lock_sec_rec_cons_read_sees
      
      flush_cached_records() was not correctly checking for errors after calling
      Item::val_xxx() methods. The expressions may contain subqueries
      or stored procedures that cause errors that should stop the statement.
      Fixed by correctly checking for errors and propagating them up the call stack.

    added:
      mysql-test/r/bug39022.result
      mysql-test/t/bug39022.test
    modified:
      sql/sql_select.cc
 3363 Sergey Glukhov	2010-02-05
      Bug#47736 killing a select from a view when the view is processing a function, asserts
      hide_view_error() does not take into account that thread query may be killed.
      Added a check for thd->killed.
      Addon: backported bug32140 fix from 6.0
     @ mysql-test/r/sp_notembedded.result
        test case
     @ mysql-test/t/sp_notembedded.test
        test case
     @ sql/sp.cc
        backported bug32140 fix from 6.0
     @ sql/table.cc
        Added a check for thd->killed.

    modified:
      mysql-test/r/sp_notembedded.result
      mysql-test/t/sp_notembedded.test
      sql/sp.cc
      sql/table.cc
=== added file 'mysql-test/r/bug39022.result'
--- a/mysql-test/r/bug39022.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/bug39022.result	2009-12-23 10:45:18 +0000
@@ -0,0 +1,32 @@
+#
+# Bug #39022: Mysql randomly crashing in lock_sec_rec_cons_read_sees
+#
+CREATE TABLE t1(a TINYINT NOT NULL,b TINYINT,PRIMARY KEY(b)) ENGINE=innodb;
+CREATE TABLE t2(d TINYINT NOT NULL,UNIQUE KEY(d)) ENGINE=innodb;
+INSERT INTO t1 VALUES (13,0),(8,1),(9,2),(6,3),
+(11,5),(11,6),(7,7),(7,8),(4,9),(6,10),(3,11),(11,12),
+(12,13),(7,14);
+INSERT INTO t2 VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),
+(11),(12),(13),(14);
+# in thread1
+START TRANSACTION;
+# in thread2
+REPLACE INTO t2 VALUES (-17);
+SELECT d FROM t2,t1 WHERE d=(SELECT MAX(a) FROM t1 WHERE t1.a > t2.d);
+d
+# in thread1
+REPLACE INTO t1(a,b) VALUES (67,20);
+# in thread2
+COMMIT;
+START TRANSACTION;
+REPLACE INTO t1(a,b) VALUES (65,-50);
+REPLACE INTO t2 VALUES (-91);
+SELECT d FROM t2,t1 WHERE d=(SELECT MAX(a) FROM t1 WHERE t1.a > t2.d);
+# in thread1
+# should not crash
+SELECT d FROM t2,t1 WHERE d=(SELECT MAX(a) FROM t1 WHERE t1.a > t2.d);
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+# in thread2
+d
+# in default
+DROP TABLE t1,t2;

=== added file 'mysql-test/t/bug39022.test'
--- a/mysql-test/t/bug39022.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/bug39022.test	2009-12-23 10:45:18 +0000
@@ -0,0 +1,58 @@
+-- source include/have_log_bin.inc
+-- source include/have_innodb.inc
+
+--echo #
+--echo # Bug #39022: Mysql randomly crashing in lock_sec_rec_cons_read_sees
+--echo #
+
+CREATE TABLE t1(a TINYINT NOT NULL,b TINYINT,PRIMARY KEY(b)) ENGINE=innodb;
+CREATE TABLE t2(d TINYINT NOT NULL,UNIQUE KEY(d)) ENGINE=innodb;
+INSERT INTO t1 VALUES (13,0),(8,1),(9,2),(6,3),
+(11,5),(11,6),(7,7),(7,8),(4,9),(6,10),(3,11),(11,12),
+(12,13),(7,14);
+INSERT INTO t2 VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),
+(11),(12),(13),(14);
+
+connect (thread1, localhost, root,,);
+connect (thread2, localhost, root,,);
+
+connection thread1;
+--echo # in thread1
+START TRANSACTION;
+
+connection thread2;
+--echo # in thread2
+REPLACE INTO t2 VALUES (-17);
+SELECT d FROM t2,t1 WHERE d=(SELECT MAX(a) FROM t1 WHERE t1.a > t2.d);
+
+connection thread1;
+--echo # in thread1
+REPLACE INTO t1(a,b) VALUES (67,20);
+
+connection thread2;
+--echo # in thread2
+COMMIT;
+START TRANSACTION;
+REPLACE INTO t1(a,b) VALUES (65,-50);
+REPLACE INTO t2 VALUES (-91);
+send;
+SELECT d FROM t2,t1 WHERE d=(SELECT MAX(a) FROM t1 WHERE t1.a > t2.d); #waits
+
+connection thread1;
+--echo # in thread1
+
+--echo # should not crash
+--error ER_LOCK_DEADLOCK
+SELECT d FROM t2,t1 WHERE d=(SELECT MAX(a) FROM t1 WHERE t1.a > t2.d); #crashes
+
+connection thread2;
+--echo # in thread2
+REAP;
+
+connection default;
+--echo # in default
+
+disconnect thread1;
+disconnect thread2;
+
+DROP TABLE t1,t2;

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2010-02-04 16:51:55 +0000
+++ b/sql/sql_select.cc	2009-12-23 10:45:18 +0000
@@ -11521,21 +11521,45 @@ flush_cached_records(JOIN *join,JOIN_TAB
       return NESTED_LOOP_KILLED; // Aborted by user /* purecov: inspected */
     }
     SQL_SELECT *select=join_tab->select;
-    if (rc == NESTED_LOOP_OK &&
-        (!join_tab->cache.select || !join_tab->cache.select->skip_record()))
+    if (rc == NESTED_LOOP_OK)
     {
-      uint i;
-      reset_cache_read(&join_tab->cache);
-      for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;)
+      bool consider_record= !join_tab->cache.select || 
+        !join_tab->cache.select->skip_record();
+
+      /*
+        Check for error: skip_record() can execute code by calling
+        Item_subselect::val_*. We need to check for errors (if any)
+        after such call.
+      */
+      if (join->thd->is_error())
+      {
+        reset_cache_write(&join_tab->cache);
+        return NESTED_LOOP_ERROR;
+      }
+
+      if (consider_record)  
       {
-	read_cached_record(join_tab);
-	if (!select || !select->skip_record())
+        uint i;
+        reset_cache_read(&join_tab->cache);
+        for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;)
         {
-          rc= (join_tab->next_select)(join,join_tab+1,0);
-	  if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
+          read_cached_record(join_tab);
+          if (!select || !select->skip_record())
           {
-            reset_cache_write(&join_tab->cache);
-            return rc;
+            /*
+              Check for error: skip_record() can execute code by calling
+              Item_subselect::val_*. We need to check for errors (if any)
+              after such call.
+              */
+            if (join->thd->is_error())
+              rc= NESTED_LOOP_ERROR;
+            else
+              rc= (join_tab->next_select)(join,join_tab+1,0);
+            if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
+            {
+              reset_cache_write(&join_tab->cache);
+              return rc;
+            }
           }
         }
       }


Attachment: [text/bzr-bundle] bzr/joro@sun.com-20091223104518-o29t0i3thgs7wgm1.bundle
Thread
bzr push into mysql-5.1-bugteam branch (joro:3363 to 3364) Bug#39022Georgi Kodinov5 Feb