diff --git a/buf/buf0buf.c b/buf/buf0buf.c index 7f5ce7c5462..0ae49b180e5 100644 --- a/buf/buf0buf.c +++ b/buf/buf0buf.c @@ -1600,6 +1600,12 @@ buf_pool_watch_is_sentinel( buf_pool_t* buf_pool, /*!< buffer pool instance */ const buf_page_t* bpage) /*!< in: block */ { +#ifdef UNIV_SYNC_DEBUG + ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_SHARED) + || rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX) + || mutex_own(buf_page_get_mutex(bpage))); +#endif + ut_ad(buf_page_in_file(bpage)); if (bpage < &buf_pool->watch[0] @@ -2048,7 +2054,9 @@ err_exit: mutex_enter(&buf_pool->LRU_list_mutex); mutex_enter(block_mutex); - if (UNIV_UNLIKELY(bpage->space != space + if (UNIV_UNLIKELY((buf_page_get_state(bpage) + != BUF_BLOCK_FILE_PAGE) + || bpage->space != space || bpage->offset != offset || !bpage->in_LRU_list || !bpage->zip.data)) { diff --git a/buf/buf0flu.c b/buf/buf0flu.c index dda0630c09a..0afdeb3fd02 100644 --- a/buf/buf0flu.c +++ b/buf/buf0flu.c @@ -1606,7 +1606,11 @@ buf_flush_page_and_try_neighbors( } ut_a(buf_page_in_file(bpage) - || buf_page_get_state(bpage) == BUF_BLOCK_REMOVE_HASH); + || (buf_page_get_state(bpage) == BUF_BLOCK_REMOVE_HASH +#ifdef UNIV_DEBUG + && !mutex_own(&buf_pool->LRU_list_mutex) +#endif + )); if (buf_flush_ready_for_flush(bpage, flush_type)) { ulint space; diff --git a/buf/buf0lru.c b/buf/buf0lru.c index 5fd590f50ca..4f43f2633f1 100644 --- a/buf/buf0lru.c +++ b/buf/buf0lru.c @@ -177,20 +177,15 @@ UNIV_INLINE ibool buf_LRU_evict_from_unzip_LRU( /*=========================*/ - buf_pool_t* buf_pool, - ibool have_LRU_mutex) + buf_pool_t* buf_pool) { ulint io_avg; ulint unzip_avg; - //ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); - if (!have_LRU_mutex) - mutex_enter(&buf_pool->LRU_list_mutex); /* If the unzip_LRU list is empty, we can only use the LRU. */ if (UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0) { - if (!have_LRU_mutex) - mutex_exit(&buf_pool->LRU_list_mutex); return(FALSE); } @@ -199,20 +194,14 @@ buf_LRU_evict_from_unzip_LRU( decompressed pages in the buffer pool. */ if (UT_LIST_GET_LEN(buf_pool->unzip_LRU) <= UT_LIST_GET_LEN(buf_pool->LRU) / 10) { - if (!have_LRU_mutex) - mutex_exit(&buf_pool->LRU_list_mutex); return(FALSE); } /* If eviction hasn't started yet, we assume by default that a workload is disk bound. */ if (buf_pool->freed_page_clock == 0) { - if (!have_LRU_mutex) - mutex_exit(&buf_pool->LRU_list_mutex); return(TRUE); } - if (!have_LRU_mutex) - mutex_exit(&buf_pool->LRU_list_mutex); /* Calculate the average over past intervals, and add the values of the current interval. */ @@ -612,6 +601,8 @@ buf_flush_or_remove_pages( ibool all_freed = TRUE; ibool must_restart = FALSE; + ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); + buf_flush_list_mutex_enter(buf_pool); for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list); @@ -930,19 +921,18 @@ ibool buf_LRU_free_from_unzip_LRU_list( /*=============================*/ buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ulint n_iterations, /*!< in: how many times this has + ulint n_iterations) /*!< in: how many times this has been called repeatedly without result: a high value means that we should search farther; we will search n_iterations / 5 of the unzip_LRU list, or nothing if n_iterations >= 5 */ - ibool have_LRU_mutex) { buf_block_t* block; ulint distance; - //ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); /* Theoratically it should be much easier to find a victim from unzip_LRU as we can choose even a dirty block (as we'll @@ -952,7 +942,7 @@ buf_LRU_free_from_unzip_LRU_list( if we have done five iterations so far. */ if (UNIV_UNLIKELY(n_iterations >= 5) - || !buf_LRU_evict_from_unzip_LRU(buf_pool, have_LRU_mutex)) { + || !buf_LRU_evict_from_unzip_LRU(buf_pool)) { return(FALSE); } @@ -960,25 +950,18 @@ buf_LRU_free_from_unzip_LRU_list( distance = 100 + (n_iterations * UT_LIST_GET_LEN(buf_pool->unzip_LRU)) / 5; -restart: for (block = UT_LIST_GET_LAST(buf_pool->unzip_LRU); UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0); block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) { ibool freed; - mutex_enter(&block->mutex); - if (!block->in_unzip_LRU_list || !block->page.in_LRU_list - || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) { - mutex_exit(&block->mutex); - goto restart; - } - ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); ut_ad(block->in_unzip_LRU_list); ut_ad(block->page.in_LRU_list); - freed = buf_LRU_free_block(&block->page, FALSE, have_LRU_mutex); + mutex_enter(&block->mutex); + freed = buf_LRU_free_block(&block->page, FALSE, TRUE); mutex_exit(&block->mutex); if (freed) { @@ -997,46 +980,35 @@ ibool buf_LRU_free_from_common_LRU_list( /*==============================*/ buf_pool_t* buf_pool, - ulint n_iterations, + ulint n_iterations) /*!< in: how many times this has been called repeatedly without result: a high value means that we should search farther; if n_iterations < 10, then we search n_iterations / 10 * buf_pool->curr_size pages from the end of the LRU list */ - ibool have_LRU_mutex) { buf_page_t* bpage; ulint distance; - //ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); distance = 100 + (n_iterations * buf_pool->curr_size) / 10; -restart: for (bpage = UT_LIST_GET_LAST(buf_pool->LRU); UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0); bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) { ibool freed; unsigned accessed; - mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); - - if (!block_mutex) { - goto restart; - } - - if (!bpage->in_LRU_list - || !buf_page_in_file(bpage)) { - mutex_exit(block_mutex); - goto restart; - } + mutex_t* block_mutex = buf_page_get_mutex(bpage); ut_ad(buf_page_in_file(bpage)); ut_ad(bpage->in_LRU_list); + mutex_enter(block_mutex); accessed = buf_page_is_accessed(bpage); - freed = buf_LRU_free_block(bpage, TRUE, have_LRU_mutex); + freed = buf_LRU_free_block(bpage, TRUE, TRUE); mutex_exit(block_mutex); if (freed) { @@ -1073,23 +1045,18 @@ buf_LRU_search_and_free_block( n_iterations / 5 of the unzip_LRU list. */ { ibool freed = FALSE; - ibool have_LRU_mutex = FALSE; - if (UT_LIST_GET_LEN(buf_pool->unzip_LRU)) - have_LRU_mutex = TRUE; + mutex_enter(&buf_pool->LRU_list_mutex); - //buf_pool_mutex_enter(buf_pool); - if (have_LRU_mutex) - mutex_enter(&buf_pool->LRU_list_mutex); - - freed = buf_LRU_free_from_unzip_LRU_list(buf_pool, n_iterations, have_LRU_mutex); + freed = buf_LRU_free_from_unzip_LRU_list(buf_pool, n_iterations); if (!freed) { freed = buf_LRU_free_from_common_LRU_list( - buf_pool, n_iterations, have_LRU_mutex); + buf_pool, n_iterations); } buf_pool_mutex_enter(buf_pool); + if (!freed) { buf_pool->LRU_flush_ended = 0; } else if (buf_pool->LRU_flush_ended > 0) { @@ -1097,8 +1064,8 @@ buf_LRU_search_and_free_block( } buf_pool_mutex_exit(buf_pool); - if (have_LRU_mutex) - mutex_exit(&buf_pool->LRU_list_mutex); + + mutex_exit(&buf_pool->LRU_list_mutex); return(freed); } diff --git a/buf/buf0rea.c b/buf/buf0rea.c index 44db27cf943..e4e6415c341 100644 --- a/buf/buf0rea.c +++ b/buf/buf0rea.c @@ -340,9 +340,13 @@ buf_read_ahead_random( return(0); } + buf_pool_mutex_exit(buf_pool); + /* Count how many blocks in the area have been recently accessed, that is, reside near the start of the LRU list. */ + rw_lock_s_lock(&buf_pool->page_hash_latch); + for (i = low; i < high; i++) { const buf_page_t* bpage = buf_page_hash_get(buf_pool, space, i); @@ -356,13 +360,13 @@ buf_read_ahead_random( if (recent_blocks >= BUF_READ_AHEAD_RANDOM_THRESHOLD(buf_pool)) { - buf_pool_mutex_exit(buf_pool); + rw_lock_s_unlock(&buf_pool->page_hash_latch); goto read_ahead; } } } - buf_pool_mutex_exit(buf_pool); + rw_lock_s_unlock(&buf_pool->page_hash_latch); /* Do nothing */ return(0); diff --git a/include/buf0buf.ic b/include/buf0buf.ic index 18c46b6412e..f214112c7ce 100644 --- a/include/buf0buf.ic +++ b/include/buf0buf.ic @@ -689,6 +689,11 @@ buf_page_get_block( /*===============*/ buf_page_t* bpage) /*!< in: control block, or NULL */ { +#ifdef UNIV_SYNC_DEBUG + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_SHARED) + || rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX)); +#endif if (UNIV_LIKELY(bpage != NULL)) { ut_ad(buf_page_in_file(bpage)); diff --git a/include/univ.i b/include/univ.i index 43eec268805..5e017ee513a 100644 --- a/include/univ.i +++ b/include/univ.i @@ -64,10 +64,10 @@ component, i.e. we show M.N.P as M.N */ (INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR) #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 35.0 +#define PERCONA_INNODB_VERSION 35.2 #endif -#define INNODB_VERSION_STR MYSQL_SERVER_VERSION "-" IB_TO_STR(PERCONA_INNODB_VERSION) +#define INNODB_VERSION_STR MYSQL_SERVER_VERSION #define REFMAN "http://dev.mysql.com/doc/refman/" \ IB_TO_STR(MYSQL_MAJOR_VERSION) "." \ diff --git a/row/row0ins.c b/row/row0ins.c index af2692b2f2e..6548e6abba9 100644 --- a/row/row0ins.c +++ b/row/row0ins.c @@ -143,6 +143,7 @@ row_ins_alloc_sys_fields( const dict_col_t* col; dfield_t* dfield; byte* ptr; + uint len; row = node->row; table = node->table; @@ -151,35 +152,37 @@ row_ins_alloc_sys_fields( ut_ad(row && table && heap); ut_ad(dtuple_get_n_fields(row) == dict_table_get_n_cols(table)); - /* 1. Allocate buffer for row id */ + /* allocate buffer to hold the needed system created hidden columns. */ + len = DATA_ROW_ID_LEN + DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN; + ptr = mem_heap_zalloc(heap, len); + /* 1. Populate row-id */ col = dict_table_get_sys_col(table, DATA_ROW_ID); dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); - ptr = mem_heap_zalloc(heap, DATA_ROW_ID_LEN); - dfield_set_data(dfield, ptr, DATA_ROW_ID_LEN); node->row_id_buf = ptr; - /* 3. Allocate buffer for trx id */ + ptr += DATA_ROW_ID_LEN; + /* 2. Populate trx id */ col = dict_table_get_sys_col(table, DATA_TRX_ID); dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); - ptr = mem_heap_zalloc(heap, DATA_TRX_ID_LEN); dfield_set_data(dfield, ptr, DATA_TRX_ID_LEN); node->trx_id_buf = ptr; - /* 4. Allocate buffer for roll ptr */ + ptr += DATA_TRX_ID_LEN; + + /* 3. Populate roll ptr */ col = dict_table_get_sys_col(table, DATA_ROLL_PTR); dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); - ptr = mem_heap_zalloc(heap, DATA_ROLL_PTR_LEN); dfield_set_data(dfield, ptr, DATA_ROLL_PTR_LEN); }