summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <jan@hundin.mysql.fi>2005-07-22 14:10:03 +0300
committerunknown <jan@hundin.mysql.fi>2005-07-22 14:10:03 +0300
commit6fd13aaa3ccc470f03c51686f781651c9709154e (patch)
tree883851cd5501311efd796192fc3f483fd158d9d6 /innobase
parentadf5fdcd7413c110b2b27f118f41eb249c781e4e (diff)
downloadmariadb-git-6fd13aaa3ccc470f03c51686f781651c9709154e.tar.gz
Implement MySQL framework to support consistent read views in
cursors for InnoDB. The idea of the patch is that if MySQL requests a consistent read view, we open one when open a cursor, set is as the active view to a transaction when fetch from the cursor, and close together with cursor close. This patch is associated to bugs #11813, #11832, and #11833. Contains after review fixes.
Diffstat (limited to 'innobase')
-rw-r--r--innobase/include/read0read.h40
-rw-r--r--innobase/include/read0types.h1
-rw-r--r--innobase/include/trx0trx.h15
-rw-r--r--innobase/read/read0read.c141
-rw-r--r--innobase/row/row0sel.c8
-rw-r--r--innobase/trx/trx0trx.c28
6 files changed, 222 insertions, 11 deletions
diff --git a/innobase/include/read0read.h b/innobase/include/read0read.h
index db6bf888095..1a7a86470a8 100644
--- a/innobase/include/read0read.h
+++ b/innobase/include/read0read.h
@@ -69,6 +69,35 @@ read_view_print(
/*============*/
read_view_t* view); /* in: read view */
+/*************************************************************************
+Create a consistent cursor view for mysql to be used in cursors. In this
+consistent read view modifications done by the creating transaction or future
+transactions are not visible. */
+
+cursor_view_t*
+read_cursor_view_create_for_mysql(
+/*==============================*/
+ trx_t* cr_trx);/* in: trx where cursor view is created */
+
+/*************************************************************************
+Close a given consistent cursor view for and restore global read view
+back to a transaction. */
+
+void
+read_cursor_view_close_for_mysql(
+/*=============================*/
+ trx_t* trx, /* in: trx */
+ cursor_view_t* curview); /* in: cursor view to be closed */
+/*************************************************************************
+This function sets a given consistent cursor view to a transaction
+read view if given consistent cursor view is not null. Otherwice, function
+restores a global read view to a transaction read view. */
+
+void
+read_cursor_set_for_mysql(
+/*======================*/
+ trx_t* trx, /* in: transaction where cursor is set */
+ cursor_view_t* curview);/* in: consistent cursor view to be set */
/* Read view lists the trx ids of those transactions for which a consistent
read should not see the modifications to the database. */
@@ -100,6 +129,17 @@ struct read_view_struct{
/* List of read views in trx_sys */
};
+/* Implement InnoDB framework to support consistent read views in
+cursors. This struct holds both heap where consistent read view
+is allocated and pointer to a read view. */
+
+struct cursor_view_struct{
+ mem_heap_t* heap;
+ /* Memory heap for the cursor view */
+ read_view_t* read_view;
+ /* Consistent read view of the cursor*/
+};
+
#ifndef UNIV_NONINL
#include "read0read.ic"
#endif
diff --git a/innobase/include/read0types.h b/innobase/include/read0types.h
index 5eb3e533f89..7d42728523e 100644
--- a/innobase/include/read0types.h
+++ b/innobase/include/read0types.h
@@ -10,5 +10,6 @@ Created 2/16/1997 Heikki Tuuri
#define read0types_h
typedef struct read_view_struct read_view_t;
+typedef struct cursor_view_struct cursor_view_t;
#endif
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 146730d46f8..2fc4d5a289f 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -602,8 +602,19 @@ struct trx_struct{
UT_LIST_BASE_NODE_T(lock_t)
trx_locks; /* locks reserved by the transaction */
/*------------------------------*/
- mem_heap_t* read_view_heap; /* memory heap for the read view */
- read_view_t* read_view; /* consistent read view or NULL */
+ mem_heap_t* global_read_view_heap;
+ /* memory heap for the global read
+ view */
+ read_view_t* global_read_view;
+ /* consistent read view used in the
+ transaction is stored here if
+ transaction is using a consistent
+ read view associated to a cursor */
+ read_view_t* read_view; /* consistent read view used in the
+ transaction or NULL, this read view
+ can be normal read view associated
+ to a transaction or read view
+ associated to a cursor */
/*------------------------------*/
UT_LIST_BASE_NODE_T(trx_named_savept_t)
trx_savepoints; /* savepoints set with SAVEPOINT ...,
diff --git a/innobase/read/read0read.c b/innobase/read/read0read.c
index 0c4a037508e..76df7cdbee0 100644
--- a/innobase/read/read0read.c
+++ b/innobase/read/read0read.c
@@ -212,15 +212,16 @@ read_view_close_for_mysql(
/*======================*/
trx_t* trx) /* in: trx which has a read view */
{
- ut_a(trx->read_view);
+ ut_a(trx->global_read_view);
mutex_enter(&kernel_mutex);
- read_view_close(trx->read_view);
+ read_view_close(trx->global_read_view);
- mem_heap_empty(trx->read_view_heap);
+ mem_heap_empty(trx->global_read_view_heap);
trx->read_view = NULL;
+ trx->global_read_view = NULL;
mutex_exit(&kernel_mutex);
}
@@ -258,3 +259,137 @@ read_view_print(
(ulong) ut_dulint_get_low(read_view_get_nth_trx_id(view, i)));
}
}
+
+/*************************************************************************
+Create a consistent cursor view for mysql to be used in cursors. In this
+consistent read view modifications done by the creating transaction or future
+transactions are not visible. */
+
+cursor_view_t*
+read_cursor_view_create_for_mysql(
+/*==============================*/
+ trx_t* cr_trx) /* in: trx where cursor view is created */
+{
+ cursor_view_t* curview;
+ read_view_t* view;
+ mem_heap_t* heap;
+ trx_t* trx;
+ ulint n;
+
+ ut_a(cr_trx);
+
+ /* Use larger heap than in trx_create when creating a read_view
+ because cursors are quite long. */
+
+ heap = mem_heap_create(512);
+
+ curview = (cursor_view_t*) mem_heap_alloc(heap, sizeof(cursor_view_t));
+ curview->heap = heap;
+
+ mutex_enter(&kernel_mutex);
+
+ curview->read_view = read_view_create_low(
+ UT_LIST_GET_LEN(trx_sys->trx_list),
+ curview->heap);
+
+ view = curview->read_view;
+ view->creator = cr_trx;
+
+ /* No future transactions should be visible in the view */
+
+ view->low_limit_no = trx_sys->max_trx_id;
+ view->low_limit_id = view->low_limit_no;
+
+ view->can_be_too_old = FALSE;
+
+ n = 0;
+ trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
+
+ /* No active transaction should be visible, not even cr_trx !*/
+
+ while (trx) {
+ if (trx->conc_state == TRX_ACTIVE ||
+ trx->conc_state == TRX_PREPARED) {
+
+ read_view_set_nth_trx_id(view, n, trx->id);
+
+ n++;
+
+ /* NOTE that a transaction whose trx number is <
+ trx_sys->max_trx_id can still be active, if it is
+ in the middle of its commit! Note that when a
+ transaction starts, we initialize trx->no to
+ ut_dulint_max. */
+
+ if (ut_dulint_cmp(view->low_limit_no, trx->no) > 0) {
+
+ view->low_limit_no = trx->no;
+ }
+ }
+
+ trx = UT_LIST_GET_NEXT(trx_list, trx);
+ }
+
+ view->n_trx_ids = n;
+
+ if (n > 0) {
+ /* The last active transaction has the smallest id: */
+ view->up_limit_id = read_view_get_nth_trx_id(view, n - 1);
+ } else {
+ view->up_limit_id = view->low_limit_id;
+ }
+
+ UT_LIST_ADD_FIRST(view_list, trx_sys->view_list, view);
+
+ mutex_exit(&kernel_mutex);
+
+ return(curview);
+}
+
+/*************************************************************************
+Close a given consistent cursor view for and restore global read view
+back to a transaction. */
+
+void
+read_cursor_view_close_for_mysql(
+/*=============================*/
+ trx_t* trx, /* in: trx */
+ cursor_view_t* curview)/* in: cursor view to be closed */
+{
+ ut_a(curview);
+ ut_a(curview->read_view);
+ ut_a(curview->heap);
+
+ mutex_enter(&kernel_mutex);
+
+ read_view_close(curview->read_view);
+ trx->read_view = trx->global_read_view;
+
+ mutex_exit(&kernel_mutex);
+
+ mem_heap_free(curview->heap);
+}
+
+/*************************************************************************
+This function sets a given consistent cursor view to a transaction
+read view if given consistent cursor view is not null. Otherwice, function
+restores a global read view to a transaction read view. */
+
+void
+read_cursor_set_for_mysql(
+/*======================*/
+ trx_t* trx, /* in: transaction where cursor is set */
+ cursor_view_t* curview)/* in: consistent cursor view to be set */
+{
+ ut_a(trx);
+
+ mutex_enter(&kernel_mutex);
+
+ if (UNIV_LIKELY(curview != NULL)) {
+ trx->read_view = curview->read_view;
+ } else {
+ trx->read_view = trx->global_read_view;
+ }
+
+ mutex_exit(&kernel_mutex);
+}
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 15439bed7e7..602f5855171 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -4083,6 +4083,11 @@ normal_return:
}
func_exit:
+ /* Restore a global read view back to transaction. This forces
+ MySQL always to set cursor view before fetch if it is used. */
+
+ trx->read_view = trx->global_read_view;
+
trx->op_info = "";
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
@@ -4136,7 +4141,8 @@ row_search_check_if_query_cache_permitted(
&& !trx->read_view) {
trx->read_view = read_view_open_now(trx,
- trx->read_view_heap);
+ trx->global_read_view_heap);
+ trx->global_read_view = trx->read_view;
}
}
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 10fbf3468c0..f95491443ee 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -159,7 +159,8 @@ trx_create(
trx->auto_inc_lock = NULL;
- trx->read_view_heap = mem_heap_create(256);
+ trx->global_read_view_heap = mem_heap_create(256);
+ trx->global_read_view = NULL;
trx->read_view = NULL;
/* Set X/Open XA transaction identification to NULL */
@@ -318,10 +319,12 @@ trx_free(
ut_a(UT_LIST_GET_LEN(trx->trx_locks) == 0);
- if (trx->read_view_heap) {
- mem_heap_free(trx->read_view_heap);
+ if (trx->global_read_view_heap) {
+ mem_heap_free(trx->global_read_view_heap);
}
+ trx->global_read_view = NULL;
+
ut_a(trx->read_view == NULL);
mem_free(trx);
@@ -831,10 +834,23 @@ trx_commit_off_kernel(
lock_release_off_kernel(trx);
if (trx->read_view) {
+ /* If transaction has a global read view this case
+ means that transaction has been using a consistent
+ read view associated to a cursor. Only the global
+ read view associated to a transaction is closed
+ and read view is then removed from the transaction.
+ If read view associated to a cursor is still used
+ it must be re-registered to another transaction. */
+
+ if (UNIV_LIKELY_NULL(trx->global_read_view)) {
+ trx->read_view = trx->global_read_view;
+ }
+
read_view_close(trx->read_view);
- mem_heap_empty(trx->read_view_heap);
+ mem_heap_empty(trx->global_read_view_heap);
trx->read_view = NULL;
+ trx->global_read_view = NULL;
}
if (must_flush_log) {
@@ -964,7 +980,9 @@ trx_assign_read_view(
mutex_enter(&kernel_mutex);
if (!trx->read_view) {
- trx->read_view = read_view_open_now(trx, trx->read_view_heap);
+ trx->read_view = read_view_open_now(trx,
+ trx->global_read_view_heap);
+ trx->global_read_view = trx->read_view;
}
mutex_exit(&kernel_mutex);