diff options
author | unknown <jan@hundin.mysql.fi> | 2005-07-22 14:10:03 +0300 |
---|---|---|
committer | unknown <jan@hundin.mysql.fi> | 2005-07-22 14:10:03 +0300 |
commit | 6fd13aaa3ccc470f03c51686f781651c9709154e (patch) | |
tree | 883851cd5501311efd796192fc3f483fd158d9d6 /innobase | |
parent | adf5fdcd7413c110b2b27f118f41eb249c781e4e (diff) | |
download | mariadb-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.h | 40 | ||||
-rw-r--r-- | innobase/include/read0types.h | 1 | ||||
-rw-r--r-- | innobase/include/trx0trx.h | 15 | ||||
-rw-r--r-- | innobase/read/read0read.c | 141 | ||||
-rw-r--r-- | innobase/row/row0sel.c | 8 | ||||
-rw-r--r-- | innobase/trx/trx0trx.c | 28 |
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); |