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 */
|
||||
read_view_t* read_view;
|
||||
/* 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
|
||||
|
@ -286,6 +286,11 @@ read_cursor_view_create_for_mysql(
|
||||
curview = (cursor_view_t*) mem_heap_alloc(heap, sizeof(cursor_view_t));
|
||||
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);
|
||||
|
||||
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->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);
|
||||
|
||||
read_view_close(curview->read_view);
|
||||
|
@ -3101,12 +3101,6 @@ row_search_for_mysql(
|
||||
"InnoDB: how you can resolve the problem.\n",
|
||||
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);
|
||||
}
|
||||
|
||||
@ -4098,12 +4092,6 @@ normal_return:
|
||||
}
|
||||
|
||||
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 = "";
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
|
@ -2146,6 +2146,15 @@ innobase_close_connection(
|
||||
|
||||
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 &&
|
||||
global_system_variables.log_warnings)
|
||||
sql_print_warning("MySQL is closing a connection that has an active "
|
||||
|
@ -14179,6 +14179,66 @@ static void test_bug11901()
|
||||
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
|
||||
*/
|
||||
@ -14427,6 +14487,7 @@ static struct my_tests_st my_tests[]= {
|
||||
{ "test_bug12001", test_bug12001 },
|
||||
{ "test_bug11909", test_bug11909 },
|
||||
{ "test_bug11901", test_bug11901 },
|
||||
{ "test_bug12243", test_bug12243 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user