summaryrefslogtreecommitdiff
path: root/storage/innobase/read
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/read')
-rw-r--r--storage/innobase/read/read0read.c527
1 files changed, 0 insertions, 527 deletions
diff --git a/storage/innobase/read/read0read.c b/storage/innobase/read/read0read.c
deleted file mode 100644
index 4068cf4fa69..00000000000
--- a/storage/innobase/read/read0read.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/******************************************************
-Cursor read
-
-(c) 1997 Innobase Oy
-
-Created 2/16/1997 Heikki Tuuri
-*******************************************************/
-
-#include "read0read.h"
-
-#ifdef UNIV_NONINL
-#include "read0read.ic"
-#endif
-
-#include "srv0srv.h"
-#include "trx0sys.h"
-
-/*
--------------------------------------------------------------------------------
-FACT A: Cursor read view on a secondary index sees only committed versions
--------
-of the records in the secondary index or those versions of rows created
-by transaction which created a cursor before cursor was created even
-if transaction which created the cursor has changed that clustered index page.
-
-PROOF: We must show that read goes always to the clustered index record
-to see that record is visible in the cursor read view. Consider e.g.
-following table and SQL-clauses:
-
-create table t1(a int not null, b int, primary key(a), index(b));
-insert into t1 values (1,1),(2,2);
-commit;
-
-Now consider that we have a cursor for a query
-
-select b from t1 where b >= 1;
-
-This query will use secondary key on the table t1. Now after the first fetch
-on this cursor if we do a update:
-
-update t1 set b = 5 where b = 2;
-
-Now second fetch of the cursor should not see record (2,5) instead it should
-see record (2,2).
-
-We also should show that if we have delete t1 where b = 5; we still
-can see record (2,2).
-
-When we access a secondary key record maximum transaction id is fetched
-from this record and this trx_id is compared to up_limit_id in the view.
-If trx_id in the record is greater or equal than up_limit_id in the view
-cluster record is accessed. Because trx_id of the creating
-transaction is stored when this view was created to the list of
-trx_ids not seen by this read view previous version of the
-record is requested to be built. This is build using clustered record.
-If the secondary key record is delete marked it's corresponding
-clustered record can be already be purged only if records
-trx_id < low_limit_no. Purge can't remove any record deleted by a
-transaction which was active when cursor was created. But, we still
-may have a deleted secondary key record but no clustered record. But,
-this is not a problem because this case is handled in
-row_sel_get_clust_rec() function which is called
-whenever we note that this read view does not see trx_id in the
-record. Thus, we see correct version. Q. E. D.
-
--------------------------------------------------------------------------------
-FACT B: Cursor read view on a clustered index sees only committed versions
--------
-of the records in the clustered index or those versions of rows created
-by transaction which created a cursor before cursor was created even
-if transaction which created the cursor has changed that clustered index page.
-
-PROOF: Consider e.g.following table and SQL-clauses:
-
-create table t1(a int not null, b int, primary key(a));
-insert into t1 values (1),(2);
-commit;
-
-Now consider that we have a cursor for a query
-
-select a from t1 where a >= 1;
-
-This query will use clustered key on the table t1. Now after the first fetch
-on this cursor if we do a update:
-
-update t1 set a = 5 where a = 2;
-
-Now second fetch of the cursor should not see record (5) instead it should
-see record (2).
-
-We also should show that if we have execute delete t1 where a = 5; after
-the cursor is opened we still can see record (2).
-
-When accessing clustered record we always check if this read view sees
-trx_id stored to clustered record. By default we don't see any changes
-if record trx_id >= low_limit_id i.e. change was made transaction
-which started after transaction which created the cursor. If row
-was changed by the future transaction a previous version of the
-clustered record is created. Thus we see only committed version in
-this case. We see all changes made by committed transactions i.e.
-record trx_id < up_limit_id. In this case we don't need to do anything,
-we already see correct version of the record. We don't see any changes
-made by active transaction except creating transaction. We have stored
-trx_id of creating transaction to list of trx_ids when this view was
-created. Thus we can easily see if this record was changed by the
-creating transaction. Because we already have clustered record we can
-access roll_ptr. Using this roll_ptr we can fetch undo record.
-We can now check that undo_no of the undo record is less than undo_no of the
-trancaction which created a view when cursor was created. We see this
-clustered record only in case when record undo_no is less than undo_no
-in the view. If this is not true we build based on undo_rec previous
-version of the record. This record is found because purge can't remove
-records accessed by active transaction. Thus we see correct version. Q. E. D.
--------------------------------------------------------------------------------
-FACT C: Purge does not remove any delete marked row that is visible
--------
-to cursor view.
-
-TODO: proof this
-
-*/
-
-/*************************************************************************
-Creates a read view object. */
-UNIV_INLINE
-read_view_t*
-read_view_create_low(
-/*=================*/
- /* out, own: read view struct */
- ulint n, /* in: number of cells in the trx_ids array */
- mem_heap_t* heap) /* in: memory heap from which allocated */
-{
- read_view_t* view;
-
- view = mem_heap_alloc(heap, sizeof(read_view_t));
-
- view->n_trx_ids = n;
- view->trx_ids = mem_heap_alloc(heap, n * sizeof(dulint));
-
- return(view);
-}
-
-/*************************************************************************
-Makes a copy of the oldest existing read view, with the exception that also
-the creating trx of the oldest view is set as not visible in the 'copied'
-view. Opens a new view if no views currently exist. The view must be closed
-with ..._close. This is used in purge. */
-
-read_view_t*
-read_view_oldest_copy_or_open_new(
-/*==============================*/
- /* out, own: read view struct */
- dulint cr_trx_id, /* in: trx_id of creating
- transaction, or (0, 0) used in purge*/
- mem_heap_t* heap) /* in: memory heap from which
- allocated */
-{
- read_view_t* old_view;
- read_view_t* view_copy;
- ibool needs_insert = TRUE;
- ulint insert_done = 0;
- ulint n;
- ulint i;
-
- ut_ad(mutex_own(&kernel_mutex));
-
- old_view = UT_LIST_GET_LAST(trx_sys->view_list);
-
- if (old_view == NULL) {
-
- return(read_view_open_now(cr_trx_id, heap));
- }
-
- n = old_view->n_trx_ids;
-
- if (ut_dulint_cmp(old_view->creator_trx_id,
- ut_dulint_create(0,0)) != 0) {
- n++;
- } else {
- needs_insert = FALSE;
- }
-
- view_copy = read_view_create_low(n, heap);
-
- /* Insert the id of the creator in the right place of the descending
- array of ids, if needs_insert is TRUE: */
-
- i = 0;
- while (i < n) {
- if (needs_insert
- && (i >= old_view->n_trx_ids
- || ut_dulint_cmp(old_view->creator_trx_id,
- read_view_get_nth_trx_id(old_view, i))
- > 0)) {
-
- read_view_set_nth_trx_id(view_copy, i,
- old_view->creator_trx_id);
- needs_insert = FALSE;
- insert_done = 1;
- } else {
- read_view_set_nth_trx_id(view_copy, i,
- read_view_get_nth_trx_id(
- old_view,
- i - insert_done));
- }
-
- i++;
- }
-
- view_copy->creator_trx_id = cr_trx_id;
-
- view_copy->low_limit_no = old_view->low_limit_no;
- view_copy->low_limit_id = old_view->low_limit_id;
-
-
- if (n > 0) {
- /* The last active transaction has the smallest id: */
- view_copy->up_limit_id = read_view_get_nth_trx_id(
- view_copy, n - 1);
- } else {
- view_copy->up_limit_id = old_view->up_limit_id;
- }
-
- UT_LIST_ADD_LAST(view_list, trx_sys->view_list, view_copy);
-
- return(view_copy);
-}
-
-/*************************************************************************
-Opens a read view where exactly the transactions serialized before this
-point in time are seen in the view. */
-
-read_view_t*
-read_view_open_now(
-/*===============*/
- /* out, own: read view struct */
- dulint cr_trx_id, /* in: trx_id of creating
- transaction, or (0, 0) used in
- purge */
- mem_heap_t* heap) /* in: memory heap from which
- allocated */
-{
- read_view_t* view;
- trx_t* trx;
- ulint n;
-
- ut_ad(mutex_own(&kernel_mutex));
-
- view = read_view_create_low(UT_LIST_GET_LEN(trx_sys->trx_list), heap);
-
- view->creator_trx_id = cr_trx_id;
- view->type = VIEW_NORMAL;
- view->undo_no = ut_dulint_create(0, 0);
-
- /* 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;
-
- n = 0;
- trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
-
- /* No active transaction should be visible, except cr_trx */
-
- while (trx) {
- if (ut_dulint_cmp(trx->id, cr_trx_id) != 0
- && (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);
-
- return(view);
-}
-
-/*************************************************************************
-Closes a read view. */
-
-void
-read_view_close(
-/*============*/
- read_view_t* view) /* in: read view */
-{
- ut_ad(mutex_own(&kernel_mutex));
-
- UT_LIST_REMOVE(view_list, trx_sys->view_list, view);
-}
-
-/*************************************************************************
-Closes a consistent read view for MySQL. This function is called at an SQL
-statement end if the trx isolation level is <= TRX_ISO_READ_COMMITTED. */
-
-void
-read_view_close_for_mysql(
-/*======================*/
- trx_t* trx) /* in: trx which has a read view */
-{
- ut_a(trx->global_read_view);
-
- mutex_enter(&kernel_mutex);
-
- read_view_close(trx->global_read_view);
-
- mem_heap_empty(trx->global_read_view_heap);
-
- trx->read_view = NULL;
- trx->global_read_view = NULL;
-
- mutex_exit(&kernel_mutex);
-}
-
-/*************************************************************************
-Prints a read view to stderr. */
-
-void
-read_view_print(
-/*============*/
- read_view_t* view) /* in: read view */
-{
- ulint n_ids;
- ulint i;
-
- if (view->type == VIEW_HIGH_GRANULARITY) {
- fprintf(stderr,
- "High-granularity read view undo_n:o %lu %lu\n",
- (ulong) ut_dulint_get_high(view->undo_no),
- (ulong) ut_dulint_get_low(view->undo_no));
- } else {
- fprintf(stderr, "Normal read view\n");
- }
-
- fprintf(stderr, "Read view low limit trx n:o %lu %lu\n",
- (ulong) ut_dulint_get_high(view->low_limit_no),
- (ulong) ut_dulint_get_low(view->low_limit_no));
-
- fprintf(stderr, "Read view up limit trx id %lu %lu\n",
- (ulong) ut_dulint_get_high(view->up_limit_id),
- (ulong) ut_dulint_get_low(view->up_limit_id));
-
- fprintf(stderr, "Read view low limit trx id %lu %lu\n",
- (ulong) ut_dulint_get_high(view->low_limit_id),
- (ulong) ut_dulint_get_low(view->low_limit_id));
-
- fprintf(stderr, "Read view individually stored trx ids:\n");
-
- n_ids = view->n_trx_ids;
-
- for (i = 0; i < n_ids; i++) {
- fprintf(stderr, "Read view trx id %lu %lu\n",
- (ulong) ut_dulint_get_high(
- read_view_get_nth_trx_id(view, i)),
- (ulong) ut_dulint_get_low(
- read_view_get_nth_trx_id(view, i)));
- }
-}
-
-/*************************************************************************
-Create a high-granularity consistent cursor view for mysql to be used
-in cursors. In this consistent read view modifications done by the
-creating transaction after the cursor is created 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;
-
- /* 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(
- UT_LIST_GET_LEN(trx_sys->trx_list), curview->heap);
-
- view = curview->read_view;
- view->creator_trx_id = cr_trx->id;
- view->type = VIEW_HIGH_GRANULARITY;
- view->undo_no = cr_trx->undo_no;
-
- /* 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;
-
- n = 0;
- trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
-
- /* No active transaction should be visible */
-
- 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 mysql and restore global read view
-back to a transaction read view. */
-
-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);
-
- /* 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);
- 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. Otherwise, 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);
-}