summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Osipov <kostja@sun.com>2009-10-28 17:49:56 +0300
committerKonstantin Osipov <kostja@sun.com>2009-10-28 17:49:56 +0300
commitf130de4fb843c7623bb6cb742bc2acc5d82d7cd8 (patch)
treea4239080b67a4ed59672976e027e7266626cce21
parent97f4ca3acd6a1ecb1333af91044324b13dcc9ce8 (diff)
downloadmariadb-git-f130de4fb843c7623bb6cb742bc2acc5d82d7cd8.tar.gz
A patch and a test case for
Bug#46539 Various crashes on INSERT IGNORE SELECT + SELECT FOR UPDATE. If a transaction was rolled back inside InnoDB due to a deadlock or lock wait timeout, and the statement had IGNORE clause, the server could crash at the end of the statement or on shutdown. This was caused by the error handling infrastructure's attempt to ignore a non-ignorable error. When a transaction rollback request is raised, switch off current_select->no_error flag, so that the following error won't be ignored. Instead, we could add !thd->is_fatal_sub_stmt_error to my_message_sql(), but since in write_record() we switch off no_error, the same approach is used in thd_mark_transaction_to_rollback(). @todo: call thd_mark_transaction_to_rollback() from handler::print_error(), then we can easily make sure that the error reported by print_error is not ignored. mysql-test/r/innodb_lock_wait_timeout_1.result: Update results (Bug#46539). mysql-test/t/innodb_lock_wait_timeout_1.test: Add a test case for Bug#46539 sql/sql_class.cc: When a transaction rollback request is raised, switch of current_select->no_error flag, so that the following error won't be ignored.
-rw-r--r--mysql-test/r/innodb_lock_wait_timeout_1.result (renamed from mysql-test/r/bug40113.result)25
-rw-r--r--mysql-test/t/innodb_lock_wait_timeout_1-master.opt (renamed from mysql-test/t/bug40113-master.opt)0
-rw-r--r--mysql-test/t/innodb_lock_wait_timeout_1.test (renamed from mysql-test/t/bug40113.test)31
-rw-r--r--sql/sql_class.cc10
4 files changed, 64 insertions, 2 deletions
diff --git a/mysql-test/r/bug40113.result b/mysql-test/r/innodb_lock_wait_timeout_1.result
index 289037a3f35..77d0e2356b5 100644
--- a/mysql-test/r/bug40113.result
+++ b/mysql-test/r/innodb_lock_wait_timeout_1.result
@@ -26,4 +26,27 @@ SELECT * FROM t1;
a b
1070109 99
DROP TABLE t2, t1;
-End of 5.0 tests
+# End of 5.0 tests
+#
+# Bug#46539 Various crashes on INSERT IGNORE SELECT + SELECT
+# FOR UPDATE
+#
+drop table if exists t1;
+create table t1 (a int primary key auto_increment,
+b int, index(b)) engine=innodb;
+insert into t1 (b) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+set autocommit=0;
+begin;
+select * from t1 where b=5 for update;
+a b
+5 5
+insert ignore into t1 (b) select a as b from t1;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+# Cleanup
+#
+commit;
+set autocommit=default;
+drop table t1;
+#
+# End of 5.1 tests
+#
diff --git a/mysql-test/t/bug40113-master.opt b/mysql-test/t/innodb_lock_wait_timeout_1-master.opt
index 462f8fbe828..462f8fbe828 100644
--- a/mysql-test/t/bug40113-master.opt
+++ b/mysql-test/t/innodb_lock_wait_timeout_1-master.opt
diff --git a/mysql-test/t/bug40113.test b/mysql-test/t/innodb_lock_wait_timeout_1.test
index 6d35d0b73d3..5f33e7c8d49 100644
--- a/mysql-test/t/bug40113.test
+++ b/mysql-test/t/innodb_lock_wait_timeout_1.test
@@ -43,4 +43,33 @@ DISCONNECT addconroot;
DROP TABLE t2, t1;
---echo End of 5.0 tests
+--echo # End of 5.0 tests
+
+--echo #
+--echo # Bug#46539 Various crashes on INSERT IGNORE SELECT + SELECT
+--echo # FOR UPDATE
+--echo #
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int primary key auto_increment,
+ b int, index(b)) engine=innodb;
+insert into t1 (b) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
+set autocommit=0;
+begin;
+select * from t1 where b=5 for update;
+connect (con1, localhost, root,,);
+connection con1;
+--error ER_LOCK_WAIT_TIMEOUT
+insert ignore into t1 (b) select a as b from t1;
+connection default;
+--echo # Cleanup
+--echo #
+disconnect con1;
+commit;
+set autocommit=default;
+drop table t1;
+
+--echo #
+--echo # End of 5.1 tests
+--echo #
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index aa556810402..080839e9b42 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -3215,6 +3215,16 @@ void mark_transaction_to_rollback(THD *thd, bool all)
{
thd->is_fatal_sub_stmt_error= TRUE;
thd->transaction_rollback_request= all;
+ /*
+ Aborted transactions can not be IGNOREd.
+ Switch off the IGNORE flag for the current
+ SELECT_LEX. This should allow my_error()
+ to report the error and abort the execution
+ flow, even in presence
+ of IGNORE clause.
+ */
+ if (thd->lex->current_select)
+ thd->lex->current_select->no_error= FALSE;
}
}
/***************************************************************************