Commit b012588f authored by unknown's avatar unknown
Browse files

Backport patch of bugfix for:

- Bug #15815: Very poor performance with multiple queries running concurrently
- Bug #22868: 'Thread thrashing' with > 50 concurrent conns under an upd-intensive workloadw

This is a patch from an e-mail; it is not included in an InnoDB snapshot.

parent f168d7d8
Loading
Loading
Loading
Loading
+96 −45
Original line number Diff line number Diff line
@@ -433,6 +433,9 @@ buf_block_init(

	block->check_index_page_at_flush = FALSE;

	mutex_create(&block->mutex);
	mutex_set_level(&block->mutex, SYNC_BUF_BLOCK);

	rw_lock_create(&(block->lock));
	ut_ad(rw_lock_validate(&(block->lock)));

@@ -599,13 +602,22 @@ buf_block_make_young(
/*=================*/
	buf_block_t*	block)	/* in: block to make younger */
{
#ifdef UNIV_SYNC_DEBUG
	ut_ad(!mutex_own(&(buf_pool->mutex)));
#endif /* UNIV_SYNC_DEBUG */

	/* Note that we read freed_page_clock's without holding any mutex:
	this is allowed since the result is used only in heuristics */

	if (buf_pool->freed_page_clock >= block->freed_page_clock 
				+ 1 + (buf_pool->curr_size / 1024)) {
				+ 1 + (buf_pool->curr_size / 4)) {

		mutex_enter(&buf_pool->mutex);
		/* There has been freeing activity in the LRU list:
		best to move to the head of the LRU list */

		buf_LRU_make_block_young(block);
		mutex_exit(&buf_pool->mutex);
	}
}

@@ -640,12 +652,16 @@ buf_block_free(
/*===========*/
	buf_block_t*	block)	/* in, own: block to be freed */
{
	ut_ad(block->state != BUF_BLOCK_FILE_PAGE);

	mutex_enter(&(buf_pool->mutex));

	mutex_enter(&block->mutex);

	ut_a(block->state != BUF_BLOCK_FILE_PAGE);

	buf_LRU_block_free_non_file_page(block);

	mutex_exit(&block->mutex);

	mutex_exit(&(buf_pool->mutex));
}

@@ -864,9 +880,8 @@ buf_page_get_gen(
#endif
	buf_pool->n_page_gets++;
loop:
	mutex_enter_fast(&(buf_pool->mutex));

	block = NULL;
	mutex_enter_fast(&(buf_pool->mutex));
	
	if (guess) {
		block = buf_block_align(guess);
@@ -904,6 +919,10 @@ buf_page_get_gen(
		goto loop;
	}

	mutex_enter(&block->mutex);

 	ut_a(block->state == BUF_BLOCK_FILE_PAGE);

	must_read = FALSE;
	
	if (block->io_fix == BUF_IO_READ) {
@@ -911,9 +930,9 @@ buf_page_get_gen(
		must_read = TRUE;

		if (mode == BUF_GET_IF_IN_POOL) {

			/* The page is only being read to buffer */
			mutex_exit(&(buf_pool->mutex));
			mutex_exit(&buf_pool->mutex);
			mutex_exit(&block->mutex);

			return(NULL);
		}
@@ -924,7 +943,7 @@ buf_page_get_gen(
#else
	buf_block_buf_fix_inc(block);
#endif
	buf_block_make_young(block);
	mutex_exit(&buf_pool->mutex);

	/* Check if this is the first access to the page */

@@ -932,10 +951,13 @@ buf_page_get_gen(

	block->accessed = TRUE;

	mutex_exit(&block->mutex);

	buf_block_make_young(block);

#ifdef UNIV_DEBUG_FILE_ACCESSES
	ut_a(block->file_page_was_freed == FALSE);
#endif	
	mutex_exit(&(buf_pool->mutex));

#ifdef UNIV_DEBUG
	buf_dbg_counter++;
@@ -960,13 +982,14 @@ buf_page_get_gen(
		}

		if (!success) {
			mutex_enter(&(buf_pool->mutex));
			mutex_enter(&block->mutex);

			block->buf_fix_count--;

			mutex_exit(&block->mutex);
#ifdef UNIV_SYNC_DEBUG
			rw_lock_s_unlock(&(block->debug_latch));
#endif			
			mutex_exit(&(buf_pool->mutex));

			return(NULL);
		}
@@ -1032,11 +1055,11 @@ buf_page_optimistic_get_func(

	block = buf_block_align(guess);
	
	mutex_enter(&(buf_pool->mutex));
	mutex_enter(&block->mutex);

	if (block->state != BUF_BLOCK_FILE_PAGE) {

		mutex_exit(&(buf_pool->mutex));
		mutex_exit(&block->mutex);

		return(FALSE);
	}
@@ -1046,15 +1069,14 @@ buf_page_optimistic_get_func(
#else
	buf_block_buf_fix_inc(block);
#endif
	buf_block_make_young(block);

	/* Check if this is the first access to the page */

	accessed = block->accessed;

	block->accessed = TRUE;

	mutex_exit(&(buf_pool->mutex));
	mutex_exit(&block->mutex);

	buf_block_make_young(block);

	/* Check if this is the first access to the page */

	ut_ad(!ibuf_inside() || ibuf_page(block->space, block->offset));

@@ -1069,14 +1091,15 @@ buf_page_optimistic_get_func(
	}

	if (!success) {
		mutex_enter(&(buf_pool->mutex));
		mutex_enter(&block->mutex);

		block->buf_fix_count--;

		mutex_exit(&block->mutex);

#ifdef UNIV_SYNC_DEBUG
		rw_lock_s_unlock(&(block->debug_latch));
#endif
		mutex_exit(&(buf_pool->mutex));

		return(FALSE);
	}

@@ -1090,14 +1113,15 @@ buf_page_optimistic_get_func(
			rw_lock_x_unlock(&(block->lock));
		}

		mutex_enter(&(buf_pool->mutex));
		mutex_enter(&block->mutex);

		block->buf_fix_count--;

		mutex_exit(&block->mutex);

#ifdef UNIV_SYNC_DEBUG
		rw_lock_s_unlock(&(block->debug_latch));
#endif
		mutex_exit(&(buf_pool->mutex));
		
		return(FALSE);
	}

@@ -1156,7 +1180,7 @@ buf_page_get_known_nowait(

	block = buf_block_align(guess);
	
	mutex_enter(&(buf_pool->mutex));
	mutex_enter(&block->mutex);

	if (block->state == BUF_BLOCK_REMOVE_HASH) {
	        /* Another thread is just freeing the block from the LRU list
@@ -1166,7 +1190,7 @@ buf_page_get_known_nowait(
		we have already removed it from the page address hash table
		of the buffer pool. */

	        mutex_exit(&(buf_pool->mutex));
		mutex_exit(&block->mutex);

		return(FALSE);
	}
@@ -1176,12 +1200,12 @@ buf_page_get_known_nowait(
#else
	buf_block_buf_fix_inc(block);
#endif
	mutex_exit(&block->mutex);

	if (mode == BUF_MAKE_YOUNG) {
		buf_block_make_young(block);
	}

	mutex_exit(&(buf_pool->mutex));

	ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));

	if (rw_latch == RW_S_LATCH) {
@@ -1195,13 +1219,15 @@ buf_page_get_known_nowait(
	}
	
	if (!success) {
		mutex_enter(&(buf_pool->mutex));
		mutex_enter(&block->mutex);
		
		block->buf_fix_count--;

		mutex_exit(&block->mutex);

#ifdef UNIV_SYNC_DEBUG
		rw_lock_s_unlock(&(block->debug_latch));
#endif		
		mutex_exit(&(buf_pool->mutex));

		return(FALSE);
	}
@@ -1247,7 +1273,6 @@ buf_page_init_for_backup_restore(
	block->offset 		= offset;

	block->lock_hash_val	= 0;
	block->lock_mutex	= NULL;

	block->freed_page_clock = 0;

@@ -1280,6 +1305,7 @@ buf_page_init(
{
#ifdef UNIV_SYNC_DEBUG
	ut_ad(mutex_own(&(buf_pool->mutex)));
	ut_ad(mutex_own(&(block->mutex)));
#endif /* UNIV_SYNC_DEBUG */
	ut_ad(block->state == BUF_BLOCK_READY_FOR_USE);

@@ -1293,7 +1319,6 @@ buf_page_init(
	block->check_index_page_at_flush = FALSE;
	
	block->lock_hash_val	= lock_rec_hash(space, offset);
	block->lock_mutex	= NULL;

	/* Insert into the hash table of file pages */

@@ -1362,12 +1387,15 @@ buf_page_init_for_read(
	ut_ad(block);

	mutex_enter(&(buf_pool->mutex));
	mutex_enter(&block->mutex);
	
	if (NULL != buf_page_hash_get(space, offset)) {

		/* The page is already in buf_pool, return */

		mutex_exit(&block->mutex);
		mutex_exit(&(buf_pool->mutex));

		buf_block_free(block);

		if (mode == BUF_READ_IBUF_PAGES_ONLY) {
@@ -1387,6 +1415,7 @@ buf_page_init_for_read(
	buf_LRU_add_block(block, TRUE); 	/* TRUE == to old blocks */
	
	block->io_fix = BUF_IO_READ;

	buf_pool->n_pend_reads++;
	
	/* We set a pass-type x-lock on the frame because then the same
@@ -1400,6 +1429,7 @@ buf_page_init_for_read(

	rw_lock_x_lock_gen(&(block->read_lock), BUF_IO_READ);
	
	mutex_exit(&block->mutex);
 	mutex_exit(&(buf_pool->mutex));

	if (mode == BUF_READ_IBUF_PAGES_ONLY) {
@@ -1462,6 +1492,8 @@ buf_page_create(

	block = free_block;
	
	mutex_enter(&block->mutex);

	buf_page_init(space, offset, block);

	/* The block must be put to the LRU list */
@@ -1472,13 +1504,15 @@ buf_page_create(
#else
	buf_block_buf_fix_inc(block);
#endif
	buf_pool->n_pages_created++;

	mutex_exit(&(buf_pool->mutex));

	mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);

	block->accessed = TRUE;
	
	buf_pool->n_pages_created++;

	mutex_exit(&(buf_pool->mutex));
	mutex_exit(&block->mutex);

	/* Delete possible entries for the page from the insert buffer:
	such can exist if the page belonged to an index which was dropped */
@@ -1516,6 +1550,12 @@ buf_page_io_complete(
	
	ut_ad(block);

	/* We do not need protect block->io_fix here by block->mutex to read
	it because this is the only function where we can change the value
	from BUF_IO_READ or BUF_IO_WRITE to some other value, and our code
	ensures that this is the only thread that handles the i/o for this
	block. */

	io_type = block->io_fix;

	if (io_type == BUF_IO_READ) {
@@ -1584,11 +1624,12 @@ buf_page_io_complete(
		}
	}
	
	mutex_enter(&(buf_pool->mutex));
	mutex_enter(&block->mutex);

#ifdef UNIV_IBUF_DEBUG
	ut_a(ibuf_count_get(block->space, block->offset) == 0);
#endif
	mutex_enter(&(buf_pool->mutex));
	
	/* Because this thread which does the unlocking is not the same that
	did the locking, we use a pass value != 0 in unlock, which simply
	removes the newest lock debug record, without checking the thread
@@ -1629,6 +1670,7 @@ buf_page_io_complete(
		}
	}
	
	mutex_exit(&block->mutex);
	mutex_exit(&(buf_pool->mutex));

	if (buf_debug_prints) {
@@ -1688,6 +1730,8 @@ buf_validate(void)

		block = buf_pool_get_nth_block(buf_pool, i);

		mutex_enter(&block->mutex);

		if (block->state == BUF_BLOCK_FILE_PAGE) {

			ut_a(buf_page_hash_get(block->space,
@@ -1731,6 +1775,8 @@ buf_validate(void)
		} else if (block->state == BUF_BLOCK_NOT_USED) {
			n_free++;
		}

		mutex_exit(&block->mutex);
 	}

	if (n_lru + n_free > buf_pool->curr_size) {
@@ -2001,16 +2047,21 @@ buf_all_freed(void)

		block = buf_pool_get_nth_block(buf_pool, i);

		mutex_enter(&block->mutex);

		if (block->state == BUF_BLOCK_FILE_PAGE) {

			if (!buf_flush_ready_for_replace(block)) {

				fprintf(stderr,
					"Page %lu %lu still fixed or dirty\n",
					block->space, block->offset);
					(ulong) block->space,
					(ulong) block->offset);
			    	ut_error;
			}
		}

		mutex_exit(&block->mutex);
 	}

	mutex_exit(&(buf_pool->mutex));
+65 −28
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ buf_flush_ready_for_replace(
{
#ifdef UNIV_SYNC_DEBUG
	ut_ad(mutex_own(&(buf_pool->mutex)));
	ut_ad(mutex_own(&block->mutex));
#endif /* UNIV_SYNC_DEBUG */
	ut_a(block->state == BUF_BLOCK_FILE_PAGE);

@@ -137,6 +138,7 @@ buf_flush_ready_for_flush(
{
#ifdef UNIV_SYNC_DEBUG
	ut_ad(mutex_own(&(buf_pool->mutex)));
	ut_ad(mutex_own(&(block->mutex)));
#endif /* UNIV_SYNC_DEBUG */
	ut_ad(block->state == BUF_BLOCK_FILE_PAGE);

@@ -507,10 +509,17 @@ buf_flush_try_page(

	block = buf_page_hash_get(space, offset);

	if (!block) {
		mutex_exit(&(buf_pool->mutex));
		return(0);
	}

	ut_a(block->state == BUF_BLOCK_FILE_PAGE);

	mutex_enter(&block->mutex);

	if (flush_type == BUF_FLUSH_LIST
	    && block && buf_flush_ready_for_flush(block, flush_type)) {
	    && buf_flush_ready_for_flush(block, flush_type)) {
	
		block->io_fix = BUF_IO_WRITE;
		block->flush_type = flush_type;
@@ -534,6 +543,7 @@ buf_flush_try_page(
			locked = TRUE;
		}

		mutex_exit(&block->mutex);
		mutex_exit(&(buf_pool->mutex));

		if (!locked) {
@@ -552,7 +562,7 @@ buf_flush_try_page(
		
		return(1);

	} else if (flush_type == BUF_FLUSH_LRU && block
	} else if (flush_type == BUF_FLUSH_LRU
		   && buf_flush_ready_for_flush(block, flush_type)) {

		/* VERY IMPORTANT:
@@ -579,13 +589,14 @@ buf_flush_try_page(
		buf_pool mutex: this ensures that the latch is acquired
		immediately. */
		
		mutex_exit(&block->mutex);
		mutex_exit(&(buf_pool->mutex));

		buf_flush_write_block_low(block);

		return(1);

	} else if (flush_type == BUF_FLUSH_SINGLE_PAGE && block
	} else if (flush_type == BUF_FLUSH_SINGLE_PAGE
		   && buf_flush_ready_for_flush(block, flush_type)) {
	
		block->io_fix = BUF_IO_WRITE;
@@ -598,6 +609,7 @@ buf_flush_try_page(

		(buf_pool->n_flush[flush_type])++;

		mutex_exit(&block->mutex);
		mutex_exit(&(buf_pool->mutex));

		rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE);
@@ -611,12 +623,13 @@ buf_flush_try_page(
		buf_flush_write_block_low(block);
		
		return(1);
	} else {
	}

	mutex_exit(&block->mutex);
	mutex_exit(&(buf_pool->mutex));

	return(0);
}
}

/***************************************************************
Flushes to disk all flushable pages within the flush area. */
@@ -659,34 +672,48 @@ buf_flush_try_neighbors(

		block = buf_page_hash_get(space, i);

		if (block && flush_type == BUF_FLUSH_LRU && i != offset
		if (!block) {

			continue;

		} else if (flush_type == BUF_FLUSH_LRU && i != offset
			   && !block->old) {

		        /* We avoid flushing 'non-old' blocks in an LRU flush,
		        because the flushed blocks are soon freed */

		        continue;
		}
		} else {

		if (block && buf_flush_ready_for_flush(block, flush_type)
			mutex_enter(&block->mutex);

			if (buf_flush_ready_for_flush(block, flush_type)
			    && (i == offset || block->buf_fix_count == 0)) {
			/* We only try to flush those neighbors != offset
			where the buf fix count is zero, as we then know that
			we probably can latch the page without a semaphore
			wait. Semaphore waits are expensive because we must
				/* We only try to flush those
				neighbors != offset where the buf fix count is
				zero, as we then know that we probably can
				latch the page without a semaphore wait.
				Semaphore waits are expensive because we must
				flush the doublewrite buffer before we start
				waiting. */

				mutex_exit(&block->mutex);

				mutex_exit(&(buf_pool->mutex));

			/* Note: as we release the buf_pool mutex above, in
			buf_flush_try_page we cannot be sure the page is still
			in a flushable state: therefore we check it again
			inside that function. */
				/* Note: as we release the buf_pool mutex
				above, in buf_flush_try_page we cannot be sure
				the page is still in a flushable state:
				therefore we check it again inside that
				function. */

			count += buf_flush_try_page(space, i, flush_type);
				count += buf_flush_try_page(space, i,
							    flush_type);

				mutex_enter(&(buf_pool->mutex));
			} else {
				mutex_exit(&block->mutex);
			}
		}
	}
				
@@ -780,12 +807,15 @@ buf_flush_batch(

	    	while ((block != NULL) && !found) {

			mutex_enter(&block->mutex);

			if (buf_flush_ready_for_flush(block, flush_type)) {

				found = TRUE;
				space = block->space;
				offset = block->offset;
	    
				mutex_exit(&block->mutex);
				mutex_exit(&(buf_pool->mutex));

				old_page_count = page_count;
@@ -803,11 +833,14 @@ buf_flush_batch(

			} else if (flush_type == BUF_FLUSH_LRU) {

				block = UT_LIST_GET_PREV(LRU, block);
				mutex_exit(&block->mutex);

				block = UT_LIST_GET_PREV(LRU, block);
			} else {
				ut_ad(flush_type == BUF_FLUSH_LIST);

				mutex_exit(&block->mutex);

				block = UT_LIST_GET_PREV(flush_list, block);
			}
	    	}
@@ -884,10 +917,14 @@ buf_flush_LRU_recommendation(void)
	       				+ BUF_FLUSH_EXTRA_MARGIN)
	       && (distance < BUF_LRU_FREE_SEARCH_LEN)) {

		mutex_enter(&block->mutex);

		if (buf_flush_ready_for_replace(block)) {
			n_replaceable++;
		}

		mutex_exit(&block->mutex);

		distance++;
			
		block = UT_LIST_GET_PREV(LRU, block);
+15 −3
Original line number Diff line number Diff line
@@ -123,6 +123,8 @@ buf_LRU_search_and_free_block(

	while (block != NULL) {

		mutex_enter(&block->mutex);

		if (buf_flush_ready_for_replace(block)) {

			if (buf_debug_prints) {
@@ -134,20 +136,24 @@ buf_LRU_search_and_free_block(
			buf_LRU_block_remove_hashed_page(block);

			mutex_exit(&(buf_pool->mutex));
			mutex_exit(&block->mutex);

			btr_search_drop_page_hash_index(block->frame);

			mutex_enter(&(buf_pool->mutex));

			ut_a(block->buf_fix_count == 0);

			buf_LRU_block_free_hashed_page(block);
			mutex_enter(&(buf_pool->mutex));
			mutex_enter(&block->mutex);

			buf_LRU_block_free_hashed_page(block);
			freed = TRUE;
			mutex_exit(&block->mutex);

			break;
		}

		mutex_exit(&block->mutex);

		block = UT_LIST_GET_PREV(LRU, block);
		distance++;

@@ -274,7 +280,10 @@ buf_LRU_get_free_block(void)
		
		block = UT_LIST_GET_FIRST(buf_pool->free);
		UT_LIST_REMOVE(free, buf_pool->free, block);

		mutex_enter(&block->mutex);
		block->state = BUF_BLOCK_READY_FOR_USE;
		mutex_exit(&block->mutex);

		mutex_exit(&(buf_pool->mutex));

@@ -636,6 +645,7 @@ buf_LRU_block_free_non_file_page(
{
#ifdef UNIV_SYNC_DEBUG
	ut_ad(mutex_own(&(buf_pool->mutex)));
	ut_ad(mutex_own(&block->mutex));
#endif /* UNIV_SYNC_DEBUG */
	ut_ad(block);
	
@@ -664,6 +674,7 @@ buf_LRU_block_remove_hashed_page(
{
#ifdef UNIV_SYNC_DEBUG
	ut_ad(mutex_own(&(buf_pool->mutex)));
	ut_ad(mutex_own(&block->mutex));
#endif /* UNIV_SYNC_DEBUG */
	ut_ad(block);
	
@@ -697,6 +708,7 @@ buf_LRU_block_free_hashed_page(
{
#ifdef UNIV_SYNC_DEBUG
	ut_ad(mutex_own(&(buf_pool->mutex)));
	ut_ad(mutex_own(&block->mutex));
#endif /* UNIV_SYNC_DEBUG */
	ut_ad(block->state == BUF_BLOCK_REMOVE_HASH);

+28 −12
Original line number Diff line number Diff line
@@ -431,8 +431,8 @@ Gets the mutex number protecting the page record lock hash chain in the lock
table. */
UNIV_INLINE
mutex_t*
buf_frame_get_lock_mutex(
/*=====================*/
buf_frame_get_mutex(
/*================*/
			/* out: mutex */
	byte*	ptr);	/* in: pointer to within a buffer frame */
/***********************************************************************
@@ -654,7 +654,10 @@ struct buf_block_struct{

	ulint		magic_n;	/* magic number to check */
	ulint		state;		/* state of the control block:
					BUF_BLOCK_NOT_USED, ... */
					BUF_BLOCK_NOT_USED, ...; changing
					this is only allowed when a thread
					has BOTH the buffer pool mutex AND
					block->mutex locked */
	byte*		frame;		/* pointer to buffer frame which
					is of size UNIV_PAGE_SIZE, and
					aligned to an address divisible by
@@ -663,8 +666,12 @@ struct buf_block_struct{
	ulint		offset;		/* page number within the space */
	ulint		lock_hash_val;	/* hashed value of the page address
					in the record lock hash table */
	mutex_t*	lock_mutex;	/* mutex protecting the chain in the
					record lock hash table */
	mutex_t		mutex;		/* mutex protecting this block:
					state (also protected by the buffer
					pool mutex), io_fix, buf_fix_count,
					and accessed; we introduce this new
					mutex in InnoDB-5.1 to relieve
					contention on the buffer pool mutex */
	rw_lock_t	lock;		/* read-write lock of the buffer
					frame */
	rw_lock_t	read_lock;	/* rw-lock reserved when a page read
@@ -720,20 +727,27 @@ struct buf_block_struct{
					in heuristic algorithms, because of
					the possibility of a wrap-around! */
	ulint		freed_page_clock;/* the value of freed_page_clock
					buffer pool when this block was
					last time put to the head of the
					LRU list */
					of the buffer pool when this block was
					the last time put to the head of the
					LRU list; a thread is allowed to
					read this for heuristic purposes
					without holding any mutex or latch */
	ibool		old;		/* TRUE if the block is in the old
					blocks in the LRU list */
	ibool		accessed;	/* TRUE if the page has been accessed
					while in the buffer pool: read-ahead
					may read in pages which have not been
					accessed yet */
					accessed yet; this is protected by
					block->mutex; a thread is allowed to
					read this for heuristic purposes
					without holding any mutex or latch */
	ulint		buf_fix_count;	/* count of how manyfold this block
					is currently bufferfixed */
					is currently bufferfixed; this is
					protected by block->mutex */
	ulint		io_fix;		/* if a read is pending to the frame,
					io_fix is BUF_IO_READ, in the case
					of a write BUF_IO_WRITE, otherwise 0 */
					of a write BUF_IO_WRITE, otherwise 0;
					this is protected by block->mutex */
	/* 4. Optimistic search field */

	dulint		modify_clock;	/* this clock is incremented every
@@ -859,7 +873,9 @@ struct buf_pool_struct{
					number of buffer blocks removed from
					the end of the LRU list; NOTE that
					this counter may wrap around at 4
					billion! */
					billion! A thread is allowed to
					read this for heuristic purposes
					without holding any mutex or latch */
	ulint		LRU_flush_ended;/* when an LRU flush ends for a page,
					this is incremented by one; this is
					set to zero when a buffer block is
+10 −11
Original line number Diff line number Diff line
@@ -357,8 +357,8 @@ Gets the mutex number protecting the page record lock hash chain in the lock
table. */
UNIV_INLINE
mutex_t*
buf_frame_get_lock_mutex(
/*=====================*/
buf_frame_get_mutex(
/*================*/
			/* out: mutex */
	byte*	ptr)	/* in: pointer to within a buffer frame */
{
@@ -366,7 +366,7 @@ buf_frame_get_lock_mutex(

	block = buf_block_align(ptr);

	return(block->lock_mutex);
	return(&block->mutex);
}

/*************************************************************************
@@ -523,6 +523,7 @@ buf_block_buf_fix_inc_debug(
	ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);

	ut_ad(ret == TRUE);
	ut_ad(mutex_own(&block->mutex));

	block->buf_fix_count++;
}
@@ -623,27 +624,25 @@ buf_page_release(
					RW_NO_LATCH */
	mtr_t*		mtr)		/* in: mtr */
{
	ulint	buf_fix_count;
	
	ut_ad(block);

	mutex_enter_fast(&(buf_pool->mutex));

	ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
	ut_ad(block->buf_fix_count > 0);

	if (rw_latch == RW_X_LATCH && mtr->modifications) {

		mutex_enter(&buf_pool->mutex);
		buf_flush_note_modification(block, mtr);
		mutex_exit(&buf_pool->mutex);
	}

	mutex_enter(&block->mutex);

#ifdef UNIV_SYNC_DEBUG
	rw_lock_s_unlock(&(block->debug_latch));
#endif
	buf_fix_count = block->buf_fix_count;
	block->buf_fix_count = buf_fix_count - 1;
	block->buf_fix_count--;

	mutex_exit(&(buf_pool->mutex));
	mutex_exit(&block->mutex);

	if (rw_latch == RW_S_LATCH) {
		rw_lock_s_unlock(&(block->lock));
Loading