summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2005-08-10 18:36:13 +0400
committerunknown <konstantin@mysql.com>2005-08-10 18:36:13 +0400
commit6861b1bf9b804f1dd8490355bb2dc1628a04bf36 (patch)
tree456848ab2f200b91bb21ed69d717cf36187eabdc /innobase
parentcf1a9d3b88a3af1b3582522d3c9702528a70e9a1 (diff)
downloadmariadb-git-6861b1bf9b804f1dd8490355bb2dc1628a04bf36.tar.gz
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. innobase/include/read0read.h: - add cursor_view_t::n_mysql_tables_in_use innobase/read/read0read.c: - 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/row/row0sel.c: - 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). sql/ha_innodb.cc: - 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. tests/mysql_client_test.c: - add a test case for Bug#12243 "MySQL Server crashes with 2 cursors (+ commit)"
Diffstat (limited to 'innobase')
-rw-r--r--innobase/include/read0read.h3
-rw-r--r--innobase/read/read0read.c9
-rw-r--r--innobase/row/row0sel.c12
3 files changed, 12 insertions, 12 deletions
diff --git a/innobase/include/read0read.h b/innobase/include/read0read.h
index b5edcefb544..7a91248cf7f 100644
--- a/innobase/include/read0read.h
+++ b/innobase/include/read0read.h
@@ -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
diff --git a/innobase/read/read0read.c b/innobase/read/read0read.c
index 334f9a8a85a..dc1ae2f1a16 100644
--- a/innobase/read/read0read.c
+++ b/innobase/read/read0read.c
@@ -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);
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 15881cb8c5d..57689520bfb 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -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);