Below is the list of changes that have just been committed into a local
5.0 repository of kostja. When kostja does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.1975 05/08/10 18:36:13 konstantin@stripped +5 -0
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.
tests/mysql_client_test.c
1.151 05/08/10 18:36:03 konstantin@stripped +61 -0
- add a test case for Bug#12243 "MySQL Server crashes with 2 cursors
(+ commit)"
sql/ha_innodb.cc
1.240 05/08/10 18:36:03 konstantin@stripped +9 -0
- add more verbose printout for the case when we close an InnoDB
connection without priorlly issuing a commit or rollback. The problem
should be investigated.
innobase/row/row0sel.c
1.99 05/08/10 18:36:02 konstantin@stripped +0 -12
- remove the restoration of the global read view from
row_search_for_mysql: MySQL may call row_search_for_mysql
more than once when fetching a row for a cursor (e.g. if there
is a WHERE clause that filters out some rows).
innobase/read/read0read.c
1.9 05/08/10 18:36:02 konstantin@stripped +9 -0
- maintain cursor_view_t::n_mysql_tables_in_use. InnoDB
maintains trx->n_mysql_tables_in_use to know when it can auto-commit
a read-only statement. When this count drops to zero,
MySQL has ended processing of such statement and InnoDB can commit.
Cursors should not break this invariant, and should exclude the tables
used in a cursor from the count of active tables.
When a cursor is closed, the number of its tables is added back,
to ensure that close_thread_tables->unlock_external->
ha_innobase::external_lock(F_UNLCK) won't drop the count in trx
below zero.
innobase/include/read0read.h
1.6 05/08/10 18:36:02 konstantin@stripped +3 -0
- add cursor_view_t::n_mysql_tables_in_use
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: konstantin
# Host: oak.local
# Root: /home/kostja/mysql/mysql-5.0-12243
--- 1.5/innobase/include/read0read.h 2005-08-03 18:08:22 +04:00
+++ 1.6/innobase/include/read0read.h 2005-08-10 18:36:02 +04:00
@@ -136,6 +136,9 @@
/* 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
--- 1.8/innobase/read/read0read.c 2005-08-03 18:08:08 +04:00
+++ 1.9/innobase/read/read0read.c 2005-08-10 18:36:02 +04:00
@@ -286,6 +286,11 @@
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(
@@ -359,6 +364,10 @@
ut_a(curview);
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);
--- 1.98/innobase/row/row0sel.c 2005-08-03 18:07:57 +04:00
+++ 1.99/innobase/row/row0sel.c 2005-08-10 18:36:02 +04:00
@@ -3101,12 +3101,6 @@
"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 @@
}
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);
--- 1.239/sql/ha_innodb.cc 2005-08-09 21:59:59 +04:00
+++ 1.240/sql/ha_innodb.cc 2005-08-10 18:36:03 +04:00
@@ -2146,6 +2146,15 @@
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 "
--- 1.150/tests/mysql_client_test.c 2005-08-10 17:45:36 +04:00
+++ 1.151/tests/mysql_client_test.c 2005-08-10 18:36:03 +04:00
@@ -14179,6 +14179,66 @@
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 @@
{ "test_bug12001", test_bug12001 },
{ "test_bug11909", test_bug11909 },
{ "test_bug11901", test_bug11901 },
+ { "test_bug12243", test_bug12243 },
{ 0, 0 }
};
| Thread |
|---|
| • bk commit into 5.0 tree (konstantin:1.1975) BUG#11832 | Konstantin Osipov | 10 Aug |