Commit 8392a814 authored by konstantin@mysql.com's avatar konstantin@mysql.com

A fix and a test case for Bug#12243 "MySQL Server crashes with 2

cursors (+ commit)" and Bug#11832 "Server crash with InnoDB + Cursors"
See comments to the changed files.
parent cacc1a9f
...@@ -136,6 +136,9 @@ struct cursor_view_struct{ ...@@ -136,6 +136,9 @@ struct cursor_view_struct{
/* Memory heap for the cursor view */ /* Memory heap for the cursor view */
read_view_t* read_view; read_view_t* read_view;
/* Consistent read view of the cursor*/ /* Consistent read view of the cursor*/
ulint n_mysql_tables_in_use;
/* number of Innobase tables used in the
processing of this cursor */
}; };
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
......
...@@ -286,6 +286,11 @@ read_cursor_view_create_for_mysql( ...@@ -286,6 +286,11 @@ read_cursor_view_create_for_mysql(
curview = (cursor_view_t*) mem_heap_alloc(heap, sizeof(cursor_view_t)); curview = (cursor_view_t*) mem_heap_alloc(heap, sizeof(cursor_view_t));
curview->heap = heap; curview->heap = heap;
/* Drop cursor tables from consideration when evaluating the need of
auto-commit */
curview->n_mysql_tables_in_use = cr_trx->n_mysql_tables_in_use;
cr_trx->n_mysql_tables_in_use = 0;
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
curview->read_view = read_view_create_low( curview->read_view = read_view_create_low(
...@@ -360,6 +365,10 @@ read_cursor_view_close_for_mysql( ...@@ -360,6 +365,10 @@ read_cursor_view_close_for_mysql(
ut_a(curview->read_view); ut_a(curview->read_view);
ut_a(curview->heap); ut_a(curview->heap);
/* Add cursor's tables to the global count of active tables that
belong to this transaction */
trx->n_mysql_tables_in_use += curview->n_mysql_tables_in_use;
mutex_enter(&kernel_mutex); mutex_enter(&kernel_mutex);
read_view_close(curview->read_view); read_view_close(curview->read_view);
......
...@@ -3101,12 +3101,6 @@ row_search_for_mysql( ...@@ -3101,12 +3101,6 @@ row_search_for_mysql(
"InnoDB: how you can resolve the problem.\n", "InnoDB: how you can resolve the problem.\n",
prebuilt->table->name); prebuilt->table->name);
/* Restore a global read view back to a transaction. This
forces MySQL always to set a cursor view before fetch from
a cursor. */
trx->read_view = trx->global_read_view;
return(DB_ERROR); return(DB_ERROR);
} }
...@@ -4098,12 +4092,6 @@ row_search_for_mysql( ...@@ -4098,12 +4092,6 @@ row_search_for_mysql(
} }
func_exit: func_exit:
/* Restore a global read view back to a transaction. This
forces MySQL always to set a cursor view before fetch from
a cursor. */
trx->read_view = trx->global_read_view;
trx->op_info = ""; trx->op_info = "";
if (UNIV_LIKELY_NULL(heap)) { if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap); mem_heap_free(heap);
......
...@@ -2146,6 +2146,15 @@ innobase_close_connection( ...@@ -2146,6 +2146,15 @@ innobase_close_connection(
ut_a(trx); ut_a(trx);
if (trx->active_trans == 0
&& trx->conc_state != TRX_NOT_STARTED) {
fprintf(stderr,
"InnoDB: Error: trx->active_trans == 0\n"
"InnoDB: but trx->conc_state != TRX_NOT_STARTED\n");
}
if (trx->conc_state != TRX_NOT_STARTED && if (trx->conc_state != TRX_NOT_STARTED &&
global_system_variables.log_warnings) global_system_variables.log_warnings)
sql_print_warning("MySQL is closing a connection that has an active " sql_print_warning("MySQL is closing a connection that has an active "
......
...@@ -14179,6 +14179,66 @@ static void test_bug11901() ...@@ -14179,6 +14179,66 @@ static void test_bug11901()
myquery(rc); myquery(rc);
} }
/* Bug#12243: multiple cursors, crash in a fetch after commit. */
static void test_bug12243()
{
MYSQL_STMT *stmt1, *stmt2;
int rc;
const char *stmt_text;
ulong type;
myheader("test_bug12243");
if (! have_innodb)
{
if (!opt_silent)
printf("This test requires InnoDB.\n");
return;
}
/* create tables */
mysql_query(mysql, "drop table if exists t1");
mysql_query(mysql, "create table t1 (a int) engine=InnoDB");
rc= mysql_query(mysql, "insert into t1 (a) values (1), (2)");
myquery(rc);
mysql_autocommit(mysql, FALSE);
/* create statement */
stmt1= mysql_stmt_init(mysql);
stmt2= mysql_stmt_init(mysql);
type= (ulong) CURSOR_TYPE_READ_ONLY;
mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
stmt_text= "select a from t1";
rc= mysql_stmt_prepare(stmt1, stmt_text, strlen(stmt_text));
check_execute(stmt1, rc);
rc= mysql_stmt_execute(stmt1);
check_execute(stmt1, rc);
rc= mysql_stmt_fetch(stmt1);
check_execute(stmt1, rc);
rc= mysql_stmt_prepare(stmt2, stmt_text, strlen(stmt_text));
check_execute(stmt2, rc);
rc= mysql_stmt_execute(stmt2);
check_execute(stmt2, rc);
rc= mysql_stmt_fetch(stmt2);
check_execute(stmt2, rc);
rc= mysql_stmt_close(stmt1);
check_execute(stmt1, rc);
rc= mysql_commit(mysql);
myquery(rc);
rc= mysql_stmt_fetch(stmt2);
check_execute(stmt2, rc);
mysql_stmt_close(stmt2);
rc= mysql_query(mysql, "drop table t1");
myquery(rc);
mysql_autocommit(mysql, TRUE); /* restore default */
}
/* /*
Read and parse arguments and MySQL options from my.cnf Read and parse arguments and MySQL options from my.cnf
*/ */
...@@ -14427,6 +14487,7 @@ static struct my_tests_st my_tests[]= { ...@@ -14427,6 +14487,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug12001", test_bug12001 }, { "test_bug12001", test_bug12001 },
{ "test_bug11909", test_bug11909 }, { "test_bug11909", test_bug11909 },
{ "test_bug11901", test_bug11901 }, { "test_bug11901", test_bug11901 },
{ "test_bug12243", test_bug12243 },
{ 0, 0 } { 0, 0 }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment