diff options
Diffstat (limited to 'storage/innodb_plugin/buf/buf0rea.c')
-rw-r--r-- | storage/innodb_plugin/buf/buf0rea.c | 209 |
1 files changed, 23 insertions, 186 deletions
diff --git a/storage/innodb_plugin/buf/buf0rea.c b/storage/innodb_plugin/buf/buf0rea.c index 319d6b2a522..dd98ea17eb5 100644 --- a/storage/innodb_plugin/buf/buf0rea.c +++ b/storage/innodb_plugin/buf/buf0rea.c @@ -38,14 +38,6 @@ Created 11/5/1995 Heikki Tuuri #include "srv0start.h" #include "srv0srv.h" -/** The size in blocks of the area where the random read-ahead algorithm counts -the accessed pages when deciding whether to read-ahead */ -#define BUF_READ_AHEAD_RANDOM_AREA BUF_READ_AHEAD_AREA - -/** There must be at least this many pages in buf_pool in the area to start -a random read-ahead */ -#define BUF_READ_AHEAD_RANDOM_THRESHOLD (1 + BUF_READ_AHEAD_RANDOM_AREA / 2) - /** The linear read-ahead area size */ #define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA @@ -62,7 +54,8 @@ flag is cleared and the x-lock released by an i/o-handler thread. @return 1 if a read request was queued, 0 if the page already resided in buf_pool, or if the page is in the doublewrite buffer blocks in which case it is never read into the pool, or if the tablespace does -not exist or is being dropped */ +not exist or is being dropped +@return 1 if read request is issued. 0 if it is not */ static ulint buf_read_page_low( @@ -165,174 +158,13 @@ buf_read_page_low( } /********************************************************************//** -Applies a random read-ahead in buf_pool if there are at least a threshold -value of accessed pages from the random read-ahead area. Does not read any -page, not even the one at the position (space, offset), if the read-ahead -mechanism is not activated. NOTE 1: the calling thread may own latches on -pages: to avoid deadlocks this function must be written such that it cannot -end up waiting for these latches! NOTE 2: the calling thread must want -access to the page given: this rule is set to prevent unintended read-aheads -performed by ibuf routines, a situation which could result in a deadlock if -the OS does not support asynchronous i/o. -@return number of page read requests issued; NOTE that if we read ibuf -pages, it may happen that the page at the given page number does not -get read even if we return a positive value! */ -static -ulint -buf_read_ahead_random( -/*==================*/ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ - ulint offset) /*!< in: page number of a page which the current thread - wants to access */ -{ - ib_int64_t tablespace_version; - ulint recent_blocks = 0; - ulint count; - ulint LRU_recent_limit; - ulint ibuf_mode; - ulint low, high; - ulint err; - ulint i; - ulint buf_read_ahead_random_area; - - /* We have currently disabled random readahead */ - return(0); - - if (srv_startup_is_before_trx_rollback_phase) { - /* No read-ahead to avoid thread deadlocks */ - return(0); - } - - if (ibuf_bitmap_page(zip_size, offset) - || trx_sys_hdr_page(space, offset)) { - - /* If it is an ibuf bitmap page or trx sys hdr, we do - no read-ahead, as that could break the ibuf page access - order */ - - return(0); - } - - /* Remember the tablespace version before we ask te tablespace size - below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we - do not try to read outside the bounds of the tablespace! */ - - tablespace_version = fil_space_get_version(space); - - buf_read_ahead_random_area = BUF_READ_AHEAD_RANDOM_AREA; - - low = (offset / buf_read_ahead_random_area) - * buf_read_ahead_random_area; - high = (offset / buf_read_ahead_random_area + 1) - * buf_read_ahead_random_area; - if (high > fil_space_get_size(space)) { - - high = fil_space_get_size(space); - } - - /* Get the minimum LRU_position field value for an initial segment - of the LRU list, to determine which blocks have recently been added - to the start of the list. */ - - LRU_recent_limit = buf_LRU_get_recent_limit(); - - buf_pool_mutex_enter(); - - if (buf_pool->n_pend_reads - > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) { - buf_pool_mutex_exit(); - - return(0); - } - - /* Count how many blocks in the area have been recently accessed, - that is, reside near the start of the LRU list. */ - - for (i = low; i < high; i++) { - const buf_page_t* bpage = buf_page_hash_get(space, i); - - if (bpage - && buf_page_is_accessed(bpage) - && (buf_page_get_LRU_position(bpage) > LRU_recent_limit)) { - - recent_blocks++; - - if (recent_blocks >= BUF_READ_AHEAD_RANDOM_THRESHOLD) { - - buf_pool_mutex_exit(); - goto read_ahead; - } - } - } - - buf_pool_mutex_exit(); - /* Do nothing */ - return(0); - -read_ahead: - /* Read all the suitable blocks within the area */ - - if (ibuf_inside()) { - ibuf_mode = BUF_READ_IBUF_PAGES_ONLY; - } else { - ibuf_mode = BUF_READ_ANY_PAGE; - } - - count = 0; - - for (i = low; i < high; i++) { - /* It is only sensible to do read-ahead in the non-sync aio - mode: hence FALSE as the first parameter */ - - if (!ibuf_bitmap_page(zip_size, i)) { - count += buf_read_page_low( - &err, FALSE, - ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, - space, zip_size, FALSE, - tablespace_version, i); - if (err == DB_TABLESPACE_DELETED) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Warning: in random" - " readahead trying to access\n" - "InnoDB: tablespace %lu page %lu,\n" - "InnoDB: but the tablespace does not" - " exist or is just being dropped.\n", - (ulong) space, (ulong) i); - } - } - } - - /* In simulated aio we wake the aio handler threads only after - queuing all aio requests, in native aio the following call does - nothing: */ - - os_aio_simulated_wake_handler_threads(); - -#ifdef UNIV_DEBUG - if (buf_debug_prints && (count > 0)) { - fprintf(stderr, - "Random read-ahead space %lu offset %lu pages %lu\n", - (ulong) space, (ulong) offset, - (ulong) count); - } -#endif /* UNIV_DEBUG */ - - ++srv_read_ahead_rnd; - return(count); -} - -/********************************************************************//** High-level function which reads a page asynchronously from a file to the buffer buf_pool if it is not already there. Sets the io_fix flag and sets an exclusive lock on the buffer frame. The flag is cleared and the x-lock -released by the i/o-handler thread. Does a random read-ahead if it seems -sensible. -@return number of page read requests issued: this can be greater than -1 if read-ahead occurred */ +released by the i/o-handler thread. +@return TRUE if page has been read in, FALSE in case of failure */ UNIV_INTERN -ulint +ibool buf_read_page( /*==========*/ ulint space, /*!< in: space id */ @@ -341,20 +173,17 @@ buf_read_page( { ib_int64_t tablespace_version; ulint count; - ulint count2; ulint err; tablespace_version = fil_space_get_version(space); - count = buf_read_ahead_random(space, zip_size, offset); - /* We do the i/o in the synchronous aio mode to save thread switches: hence TRUE */ - count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, - zip_size, FALSE, - tablespace_version, offset); - srv_buf_pool_reads+= count2; + count = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, + zip_size, FALSE, + tablespace_version, offset); + srv_buf_pool_reads += count; if (err == DB_TABLESPACE_DELETED) { ut_print_timestamp(stderr); fprintf(stderr, @@ -371,14 +200,14 @@ buf_read_page( /* Increment number of I/O operations used for LRU policy. */ buf_LRU_stat_inc_io(); - return(count + count2); + return(count > 0); } /********************************************************************//** Applies linear read-ahead if in the buf_pool the page is a border page of a linear read-ahead area and all the pages in the area have been accessed. Does not read any page if the read-ahead mechanism is not activated. Note -that the the algorithm looks at the 'natural' adjacent successor and +that the algorithm looks at the 'natural' adjacent successor and predecessor of the page, which on the leaf level of a B-tree are the next and previous page in the chain of leaves. To know these, the page specified in (space, offset) must already be present in the buf_pool. Thus, the @@ -498,9 +327,17 @@ buf_read_ahead_linear( fail_count++; } else if (pred_bpage) { - int res = (ut_ulint_cmp( - buf_page_get_LRU_position(bpage), - buf_page_get_LRU_position(pred_bpage))); + /* Note that buf_page_is_accessed() returns + the time of the first access. If some blocks + of the extent existed in the buffer pool at + the time of a linear access pattern, the first + access times may be nonmonotonic, even though + the latest access times were linear. The + threshold (srv_read_ahead_factor) should help + a little against this. */ + int res = ut_ulint_cmp( + buf_page_is_accessed(bpage), + buf_page_is_accessed(pred_bpage)); /* Accesses not in the right order */ if (res != 0 && res != asc_or_desc) { fail_count++; @@ -643,7 +480,7 @@ buf_read_ahead_linear( LRU policy decision. */ buf_LRU_stat_inc_io(); - ++srv_read_ahead_seq; + buf_pool->stat.n_ra_pages_read += count; return(count); } |