Commit f1e0cf9d authored by tsmith@quadxeon.mysql.com's avatar tsmith@quadxeon.mysql.com
Browse files

This ChangeSet must be null-merged to 5.1. Applied innodb-5.0-ss982, -ss998, -ss1003

Fixes:
- Bug #15815: Very poor performance with multiple queries running concurrently
- Bug #22868: 'Thread thrashing' with > 50 concurrent conns under an upd-intensive workloadw
- Bug #23769: Debug assertion failure with innodb_locks_unsafe_for_binlog
- Bug #24089: Race condition in fil_flush_file_spaces()
parent 41117b12
Loading
Loading
Loading
Loading
+125 −56
Original line number Diff line number Diff line
@@ -221,6 +221,9 @@ in the free list to the frames.
5) When we have AWE enabled, we disable adaptive hash indexes.
*/

/* Value in microseconds */
static const int WAIT_FOR_READ	= 20000;

buf_pool_t*	buf_pool = NULL; /* The buffer buf_pool of the database */

#ifdef UNIV_DEBUG
@@ -488,6 +491,9 @@ buf_block_init(

	block->n_pointers = 0;

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

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

@@ -756,8 +762,15 @@ buf_awe_map_page_to_frame(
	bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped);

	while (bck) {	
		if (bck->state == BUF_BLOCK_FILE_PAGE
	    	    && (bck->buf_fix_count != 0 || bck->io_fix != 0)) {
		ibool skip;

		mutex_enter(&bck->mutex);

		skip = (bck->state == BUF_BLOCK_FILE_PAGE
			&& (bck->buf_fix_count != 0 || bck->io_fix != 0));

		if (skip) {
			mutex_exit(&bck->mutex);

			/* We have to skip this */
			bck = UT_LIST_GET_PREV(awe_LRU_free_mapped, bck);
@@ -790,6 +803,8 @@ buf_awe_map_page_to_frame(

			buf_pool->n_pages_awe_remapped++;
			
			mutex_exit(&bck->mutex);

			return;
		}
	}
@@ -828,13 +843,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);
	}
}

@@ -869,12 +893,16 @@ buf_block_free(
/*===========*/
	buf_block_t*	block)	/* in, own: block to be freed */
{
	ut_a(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));
}

@@ -1093,9 +1121,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);
@@ -1133,6 +1160,8 @@ buf_page_get_gen(
		goto loop;
	}

	mutex_enter(&block->mutex);

	ut_a(block->state == BUF_BLOCK_FILE_PAGE);

	must_read = FALSE;
@@ -1142,9 +1171,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);
		}
@@ -1168,7 +1197,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 */

@@ -1176,10 +1205,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++;
@@ -1204,13 +1236,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);
		}
@@ -1221,18 +1254,16 @@ buf_page_get_gen(
			completes */

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

		                if (block->io_fix == BUF_IO_READ) {

				        mutex_exit(&(buf_pool->mutex));
				  
				        /* Sleep 20 milliseconds */
					mutex_exit(&block->mutex);
				  
				        os_thread_sleep(20000);
					os_thread_sleep(WAIT_FOR_READ);
				} else {
				  
				       mutex_exit(&(buf_pool->mutex));
					mutex_exit(&block->mutex);

				       break;
				}
@@ -1291,14 +1322,14 @@ buf_page_optimistic_get_func(
	ut_ad(mtr && block);
	ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));

	mutex_enter(&(buf_pool->mutex));

	/* If AWE is used, block may have a different frame now, e.g., NULL */

	mutex_enter(&block->mutex);

	if (UNIV_UNLIKELY(block->state != BUF_BLOCK_FILE_PAGE)
	    || UNIV_UNLIKELY(block->frame != guess)) {
	exit_func:
		mutex_exit(&(buf_pool->mutex));

		mutex_exit(&block->mutex);

		return(FALSE);
	}
@@ -1308,15 +1339,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));

@@ -1331,13 +1361,16 @@ buf_page_optimistic_get_func(
	}

	if (UNIV_UNLIKELY(!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
		goto exit_func;
		return(FALSE);
	}

	if (UNIV_UNLIKELY(!UT_DULINT_EQ(modify_clock, block->modify_clock))) {
@@ -1350,13 +1383,16 @@ 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
		goto exit_func;
		return(FALSE);
	}

	mtr_memo_push(mtr, block, fix_type);
@@ -1413,10 +1449,10 @@ buf_page_get_known_nowait(
	ut_ad(mtr);
	ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
	
	mutex_enter(&(buf_pool->mutex));

	block = buf_block_align(guess);

	mutex_enter(&block->mutex);

	if (block->state == BUF_BLOCK_REMOVE_HASH) {
	        /* Another thread is just freeing the block from the LRU list
	        of the buffer pool: do not try to access this page; this
@@ -1425,7 +1461,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);
	}
@@ -1437,12 +1473,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) {
@@ -1456,13 +1492,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);
	}
@@ -1510,7 +1548,6 @@ buf_page_init_for_backup_restore(
	block->offset 		= offset;

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

	block->freed_page_clock = 0;

@@ -1543,6 +1580,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_a(block->state != BUF_BLOCK_FILE_PAGE);

@@ -1557,7 +1595,6 @@ buf_page_init(
	block->index		= NULL;
	
	block->lock_hash_val	= lock_rec_hash(space, offset);
	block->lock_mutex	= NULL;

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

@@ -1650,6 +1687,7 @@ buf_page_init_for_read(
	ut_a(block);

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

	if (fil_tablespace_deleted_or_being_deleted_in_mem(space,
							tablespace_version)) {
@@ -1662,7 +1700,9 @@ buf_page_init_for_read(
		/* The page belongs to a space which has been deleted or is
		being deleted, or 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) {
@@ -1682,6 +1722,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
@@ -1693,6 +1734,7 @@ buf_page_init_for_read(
	
	rw_lock_x_lock_gen(&(block->lock), BUF_IO_READ);
	
	mutex_exit(&block->mutex);
 	mutex_exit(&(buf_pool->mutex));

	if (mode == BUF_READ_IBUF_PAGES_ONLY) {
@@ -1757,6 +1799,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 */
@@ -1767,13 +1811,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 */
@@ -1822,6 +1868,12 @@ buf_page_io_complete(

	ut_a(block->state == BUF_BLOCK_FILE_PAGE);

	/* 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) {
@@ -1890,11 +1942,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
@@ -1937,6 +1990,7 @@ buf_page_io_complete(
#endif /* UNIV_DEBUG */
	}
	
	mutex_exit(&block->mutex);
	mutex_exit(&(buf_pool->mutex));

#ifdef UNIV_DEBUG
@@ -1999,6 +2053,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,
@@ -2042,6 +2098,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) {
@@ -2187,11 +2245,17 @@ buf_get_latched_pages_number(void)

		block = buf_pool_get_nth_block(buf_pool, i);

               if (((block->buf_fix_count != 0) || (block->io_fix != 0)) &&
                    block->magic_n == BUF_BLOCK_MAGIC_N )
		if (block->magic_n == BUF_BLOCK_MAGIC_N) {
			mutex_enter(&block->mutex);

			if (block->buf_fix_count != 0 || block->io_fix != 0) {
				fixed_pages_number++;
			}

			mutex_exit(&block->mutex);
		}
        }

        mutex_exit(&(buf_pool->mutex));
        return fixed_pages_number;
}
@@ -2354,16 +2418,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",
					(ulong) block->space, (ulong) block->offset);
					(ulong) block->space,
					(ulong) block->offset);
			    	ut_error;
			}
		}

		mutex_exit(&block->mutex);
 	}

	mutex_exit(&(buf_pool->mutex));
+65 −27
Original line number Diff line number Diff line
@@ -114,6 +114,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 */
	if (block->state != BUF_BLOCK_FILE_PAGE) {
		ut_print_timestamp(stderr);
@@ -148,6 +149,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_a(block->state == BUF_BLOCK_FILE_PAGE);

@@ -539,8 +541,15 @@ buf_flush_try_page(

	ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE);

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

	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;

@@ -578,6 +587,7 @@ buf_flush_try_page(
			locked = TRUE;
		}

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

		if (!locked) {
@@ -598,7 +608,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:
@@ -639,13 +649,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;
@@ -672,6 +683,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);
@@ -688,12 +700,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. */
@@ -737,34 +750,48 @@ buf_flush_try_neighbors(
		block = buf_page_hash_get(space, i);
		ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE);

		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 {

			mutex_enter(&block->mutex);

		if (block && buf_flush_ready_for_flush(block, flush_type)
			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);
			}
		}
	}
				
@@ -858,12 +885,15 @@ buf_flush_batch(
	    	while ((block != NULL) && !found) {
			ut_a(block->state == BUF_BLOCK_FILE_PAGE);

			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;
@@ -881,10 +911,14 @@ buf_flush_batch(

			} else if (flush_type == BUF_FLUSH_LRU) {

				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);
			}
	    	}
@@ -966,10 +1000,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);
+24 −1
Original line number Diff line number Diff line
@@ -86,6 +86,9 @@ buf_LRU_invalidate_tablespace(
	block = UT_LIST_GET_LAST(buf_pool->LRU);

	while (block != NULL) {

		mutex_enter(&block->mutex);

	        ut_a(block->state == BUF_BLOCK_FILE_PAGE);

		if (block->space == id
@@ -112,6 +115,8 @@ buf_LRU_invalidate_tablespace(
			if (block->is_hashed) {
				page_no = block->offset;
			
				mutex_exit(&block->mutex);

				mutex_exit(&(buf_pool->mutex));

				/* Note that the following call will acquire
@@ -138,6 +143,7 @@ buf_LRU_invalidate_tablespace(
			buf_LRU_block_free_hashed_page(block);
		}
next_page:
		mutex_exit(&block->mutex);
		block = UT_LIST_GET_PREV(LRU, block);
	}

@@ -211,6 +217,9 @@ buf_LRU_search_and_free_block(

	while (block != NULL) {
	        ut_a(block->in_LRU_list);

		mutex_enter(&block->mutex);

		if (buf_flush_ready_for_replace(block)) {

#ifdef UNIV_DEBUG
@@ -225,6 +234,7 @@ buf_LRU_search_and_free_block(
			buf_LRU_block_remove_hashed_page(block);

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

			/* Remove possible adaptive hash index built on the
			page; in the case of AWE the block may not have a
@@ -233,15 +243,21 @@ buf_LRU_search_and_free_block(
			if (block->frame) {
				btr_search_drop_page_hash_index(block->frame);
			}
			mutex_enter(&(buf_pool->mutex));

			ut_a(block->buf_fix_count == 0);

			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++;

@@ -415,8 +431,12 @@ buf_LRU_get_free_block(void)
			}
		}
		
		mutex_enter(&block->mutex);

		block->state = BUF_BLOCK_READY_FOR_USE;

		mutex_exit(&block->mutex);

		mutex_exit(&(buf_pool->mutex));

		if (started_monitor) {
@@ -818,6 +838,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);
	
@@ -857,6 +878,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);
	
@@ -914,6 +936,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_a(block->state == BUF_BLOCK_REMOVE_HASH);

+9 −4
Original line number Diff line number Diff line
@@ -724,8 +724,10 @@ dict_truncate_index_tree(
				/* out: new root page number, or
				FIL_NULL on failure */
	dict_table_t*	table,	/* in: the table the index belongs to */
	rec_t*		rec,	/* in: record in the clustered index of
				SYS_INDEXES table */
	btr_pcur_t*	pcur,	/* in/out: persistent cursor pointing to
				record in the clustered index of
				SYS_INDEXES table. The cursor may be
				repositioned in this call. */
	mtr_t*		mtr)	/* in: mtr having the latch
				on the record page. The mtr may be
				committed and restarted in this call. */
@@ -734,6 +736,7 @@ dict_truncate_index_tree(
	ulint		space;
	ulint		type;
	dulint		index_id;
	rec_t*		rec;
	byte*		ptr;
	ulint		len;
	ulint		comp;
@@ -744,6 +747,7 @@ dict_truncate_index_tree(
#endif /* UNIV_SYNC_DEBUG */

	ut_a(!dict_sys->sys_indexes->comp);
	rec = btr_pcur_get_rec(pcur);
	ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);

	ut_ad(len == 4);
@@ -809,10 +813,11 @@ dict_truncate_index_tree(
	/* We will need to commit the mini-transaction in order to avoid
	deadlocks in the btr_create() call, because otherwise we would
	be freeing and allocating pages in the same mini-transaction. */
	btr_pcur_store_position(pcur, mtr);
	mtr_commit(mtr);
	/* mtr_commit() will invalidate rec. */
	rec = NULL;

	mtr_start(mtr);
	btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);

	/* Find the index corresponding to this SYS_INDEXES record. */
	for (index = UT_LIST_GET_FIRST(table->indexes);
+31 −13
Original line number Diff line number Diff line
@@ -4285,29 +4285,47 @@ fil_flush_file_spaces(
{
	fil_system_t*	system	= fil_system;
	fil_space_t*	space;
	ulint*		space_ids;
	ulint		n_space_ids;
	ulint		i;

	mutex_enter(&(system->mutex));

	space = UT_LIST_GET_FIRST(system->unflushed_spaces);
	n_space_ids = UT_LIST_GET_LEN(system->unflushed_spaces);
	if (n_space_ids == 0) {

	while (space) {
		if (space->purpose == purpose && !space->is_being_deleted) {
		mutex_exit(&system->mutex);
		return;
	}

			space->n_pending_flushes++; /* prevent dropping of the
						    space while we are
						    flushing */
			mutex_exit(&(system->mutex));
	/* Assemble a list of space ids to flush.  Previously, we
	traversed system->unflushed_spaces and called UT_LIST_GET_NEXT()
	on a space that was just removed from the list by fil_flush().
	Thus, the space could be dropped and the memory overwritten. */
	space_ids = mem_alloc(n_space_ids * sizeof *space_ids);

			fil_flush(space->id);
	n_space_ids = 0;

			mutex_enter(&(system->mutex));
	for (space = UT_LIST_GET_FIRST(system->unflushed_spaces);
	     space;
	     space = UT_LIST_GET_NEXT(unflushed_spaces, space)) {

			space->n_pending_flushes--;
		if (space->purpose == purpose && !space->is_being_deleted) {

			space_ids[n_space_ids++] = space->id;
		}
		space = UT_LIST_GET_NEXT(unflushed_spaces, space);
	}

	mutex_exit(&(system->mutex));
	mutex_exit(&system->mutex);

	/* Flush the spaces.  It will not hurt to call fil_flush() on
	a non-existing space id. */
	for (i = 0; i < n_space_ids; i++) {

		fil_flush(space_ids[i]);
	}

	mem_free(space_ids);
}

/**********************************************************************
Loading