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.
This commit is contained in:
parent
cacc1a9f0a
commit
8392a814af
@ -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(
|
|||||||
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(
|
|||||||
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(
|
|||||||
"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 @@ normal_return:
|
|||||||
}
|
}
|
||||||
|
|
||||||
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(
|
|||||||
|
|
||||||
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()
|
|||||||
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[]= {
|
|||||||
{ "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 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user