Commit 6fd13aaa authored by unknown's avatar unknown
Browse files

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.

parent adf5fdcd
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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
+13 −2
Original line number Diff line number Diff line
@@ -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 ...,
+138 −3
Original line number Diff line number Diff line
@@ -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);
}
+7 −1
Original line number Diff line number Diff line
@@ -4083,6 +4083,11 @@ row_search_for_mysql(
	}

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;
		}
	}
	
Loading