diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2016-08-12 11:17:45 +0300 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2016-09-02 13:22:28 +0300 |
commit | 2e814d4702d71a04388386a9f591d14a35980bfe (patch) | |
tree | f3f9b48d116a3738c5e71f3a360ca61f16cfb632 /storage/innobase/buf/buf0rea.cc | |
parent | 848d211c5c4df00b819cd84d7530cf7d29bb0524 (diff) | |
download | mariadb-git-2e814d4702d71a04388386a9f591d14a35980bfe.tar.gz |
Merge InnoDB 5.7 from mysql-5.7.9.
Contains also
MDEV-10547: Test multi_update_innodb fails with InnoDB 5.7
The failure happened because 5.7 has changed the signature of
the bool handler::primary_key_is_clustered() const
virtual function ("const" was added). InnoDB was using the old
signature which caused the function not to be used.
MDEV-10550: Parallel replication lock waits/deadlock handling does not work with InnoDB 5.7
Fixed mutexing problem on lock_trx_handle_wait. Note that
rpl_parallel and rpl_optimistic_parallel tests still
fail.
MDEV-10156 : Group commit tests fail on 10.2 InnoDB (branch bb-10.2-jan)
Reason: incorrect merge
MDEV-10550: Parallel replication can't sync with master in InnoDB 5.7 (branch bb-10.2-jan)
Reason: incorrect merge
Diffstat (limited to 'storage/innobase/buf/buf0rea.cc')
-rw-r--r-- | storage/innobase/buf/buf0rea.cc | 579 |
1 files changed, 280 insertions, 299 deletions
diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index 285fc465160..5de0412afb2 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2015. MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -24,11 +24,12 @@ The database buffer read Created 11/5/1995 Heikki Tuuri *******************************************************/ -#include "buf0rea.h" +#include "ha_prototypes.h" +#include <mysql/service_thd_wait.h> +#include "buf0rea.h" #include "fil0fil.h" #include "mtr0mtr.h" - #include "buf0buf.h" #include "buf0flu.h" #include "buf0lru.h" @@ -39,8 +40,6 @@ Created 11/5/1995 Heikki Tuuri #include "os0file.h" #include "srv0start.h" #include "srv0srv.h" -#include "mysql/plugin.h" -#include "mysql/service_thd_wait.h" /** There must be at least this many pages in buf_pool in the area to start a random read-ahead */ @@ -91,62 +90,50 @@ buf_read_page_handle_error( buf_pool_mutex_exit(buf_pool); } -/********************************************************************//** -Low-level function which reads a page asynchronously from a file to the +/** Low-level function which reads a page asynchronously from a file to the buffer buf_pool if it is not already there, in which case does nothing. Sets the io_fix flag and sets an exclusive lock on the buffer frame. The flag is cleared and the x-lock released by an i/o-handler thread. + +@param[out] err DB_SUCCESS, DB_TABLESPACE_DELETED or + DB_TABLESPACE_TRUNCATED if we are trying + to read from a non-existent tablespace, a + tablespace which is just now being dropped, + or a tablespace which is truncated +@param[in] sync true if synchronous aio is desired +@param[in] type IO type, SIMULATED, IGNORE_MISSING +@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ..., +@param[in] page_id page id +@param[in] unzip true=request uncompressed page @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 -@return 1 if read request is issued. 0 if it is not */ +not exist or is being dropped */ static ulint buf_read_page_low( -/*==============*/ - dberr_t* err, /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are - trying to read from a non-existent tablespace, or a - tablespace which is just now being dropped */ - bool sync, /*!< in: true if synchronous aio is desired */ - ulint mode, /*!< in: BUF_READ_IBUF_PAGES_ONLY, ..., - ORed to OS_AIO_SIMULATED_WAKE_LATER (see below - at read-ahead functions) */ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size, or 0 */ - ibool unzip, /*!< in: TRUE=request uncompressed page */ - ib_int64_t tablespace_version, /*!< in: if the space memory object has - this timestamp different from what we are giving here, - treat the tablespace as dropped; this is a timestamp we - use to stop dangling page reads from a tablespace - which we have DISCARDed + IMPORTed back */ - ulint offset, /*!< in: page number */ + dberr_t* err, + bool sync, + ulint type, + ulint mode, + const page_id_t& page_id, + const page_size_t& page_size, + bool unzip, buf_page_t** rbpage) /*!< out: page */ { buf_page_t* bpage; - ulint wake_later; - ibool ignore_nonexistent_pages; *err = DB_SUCCESS; - wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER; - mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER; - - ignore_nonexistent_pages = mode & BUF_READ_IGNORE_NONEXISTENT_PAGES; - mode &= ~BUF_READ_IGNORE_NONEXISTENT_PAGES; - - if (space == TRX_SYS_SPACE && buf_dblwr_page_inside(offset)) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Warning: trying to read" - " doublewrite buffer page %lu\n", - (ulong) offset); + if (page_id.space() == TRX_SYS_SPACE + && buf_dblwr_page_inside(page_id.page_no())) { + ib::error() << "Trying to read doublewrite buffer page " + << page_id; return(0); } - if (ibuf_bitmap_page(zip_size, offset) - || trx_sys_hdr_page(space, offset)) { + if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) { /* Trx sys header is so low in the latching order that we play safe and do not leave the i/o-completion to an asynchronous @@ -161,60 +148,81 @@ buf_read_page_low( or is being dropped; if we succeed in initing the page in the buffer pool for read, then DISCARD cannot proceed until the read has completed */ - bpage = buf_page_init_for_read(err, mode, space, zip_size, unzip, - tablespace_version, offset); + bpage = buf_page_init_for_read(err, mode, page_id, page_size, unzip); + if (bpage == NULL) { return(0); } -#ifdef UNIV_DEBUG - if (buf_debug_prints) { - fprintf(stderr, - "Posting read request for page %lu, sync %s\n", - (ulong) offset, sync ? "true" : "false"); - } -#endif + DBUG_PRINT("ib_buf", ("read page %u:%u size=%u unzip=%u,%s", + (unsigned) page_id.space(), + (unsigned) page_id.page_no(), + (unsigned) page_size.physical(), + (unsigned) unzip, + sync ? "sync" : "async")); ut_ad(buf_page_in_file(bpage)); - byte* frame = zip_size ? bpage->zip.data : ((buf_block_t*) bpage)->frame; - if (sync) { thd_wait_begin(NULL, THD_WAIT_DISKIO); } - if (zip_size) { - *err = fil_io(OS_FILE_READ | wake_later - | ignore_nonexistent_pages, - sync, space, zip_size, offset, 0, zip_size, - frame, bpage, &bpage->write_size); + void* dst; + + if (page_size.is_compressed()) { + dst = bpage->zip.data; } else { ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); - *err = fil_io(OS_FILE_READ | wake_later - | ignore_nonexistent_pages, - sync, space, 0, offset, 0, UNIV_PAGE_SIZE, - frame, bpage, - &bpage->write_size); + dst = ((buf_block_t*) bpage)->frame; } + IORequest request(type | IORequest::READ); + + ut_ad(dst != NULL); + ut_ad(bpage->zip.data != NULL || ((buf_block_t*)bpage)->frame != NULL); + + *err = fil_io( + request, sync, page_id, page_size, 0, page_size.physical(), + dst, bpage, NULL); + + ut_ad(dst != NULL); + ut_ad(bpage->zip.data != NULL || ((buf_block_t*)bpage)->frame != NULL); + ut_ad(bpage->id.space() == page_id.space()); + if (sync) { thd_wait_end(NULL); } if (*err != DB_SUCCESS) { - if (ignore_nonexistent_pages || *err == DB_TABLESPACE_DELETED) { + if (*err == DB_TABLESPACE_TRUNCATED) { + /* Remove the page which is outside the + truncated tablespace bounds when recovering + from a crash happened during a truncation */ + buf_read_page_handle_error(bpage); + if (recv_recovery_on) { + mutex_enter(&recv_sys->mutex); + ut_ad(recv_sys->n_addrs > 0); + recv_sys->n_addrs--; + mutex_exit(&recv_sys->mutex); + } + return(0); + } else if (IORequest::ignore_missing(type) + || *err == DB_TABLESPACE_DELETED) { buf_read_page_handle_error(bpage); return(0); } - /* else */ + ut_error; } if (sync) { + ut_ad(dst != NULL); + ut_ad(bpage->zip.data != NULL || ((buf_block_t*)bpage)->frame != NULL); /* The i/o is already completed when we arrive from fil_read */ + if (!buf_page_io_complete(bpage)) { if (rbpage) { *rbpage = bpage; @@ -230,8 +238,7 @@ buf_read_page_low( return(1); } -/********************************************************************//** -Applies a random read-ahead in buf_pool if there are at least a threshold +/** 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 @@ -240,24 +247,20 @@ 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. +@param[in] page_id page id of a page which the current thread +wants to access +@param[in] page_size page size +@param[in] inside_ibuf TRUE if we are inside ibuf routine @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! -@return number of page read requests issued */ -UNIV_INTERN +get read even if we return a positive value! */ 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 */ - ibool inside_ibuf) /*!< in: TRUE if we are inside ibuf - routine */ + const page_id_t& page_id, + const page_size_t& page_size, + ibool inside_ibuf) { - buf_pool_t* buf_pool = buf_pool_get(space, offset); - ib_int64_t tablespace_version; + buf_pool_t* buf_pool = buf_pool_get(page_id); ulint recent_blocks = 0; ulint ibuf_mode; ulint count; @@ -277,8 +280,7 @@ buf_read_ahead_random( return(0); } - if (ibuf_bitmap_page(zip_size, offset) - || trx_sys_hdr_page(space, offset)) { + if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) { /* If it is an ibuf bitmap page or trx sys hdr, we do no read-ahead, as that could break the ibuf page access @@ -287,19 +289,22 @@ buf_read_ahead_random( 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); - - low = (offset / buf_read_ahead_random_area) + low = (page_id.page_no() / buf_read_ahead_random_area) * buf_read_ahead_random_area; - high = (offset / buf_read_ahead_random_area + 1) + + high = (page_id.page_no() / buf_read_ahead_random_area + 1) * buf_read_ahead_random_area; - if (high > fil_space_get_size(space)) { - high = fil_space_get_size(space); + /* Remember the tablespace version before we ask the tablespace size + below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we + do not try to read outside the bounds of the tablespace! */ + if (fil_space_t* space = fil_space_acquire(page_id.space())) { + if (high > space->size) { + high = space->size; + } + fil_space_release(space); + } else { + return(0); } buf_pool_mutex_enter(buf_pool); @@ -315,10 +320,10 @@ buf_read_ahead_random( 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(buf_pool, space, i); + const buf_page_t* bpage = buf_page_hash_get( + buf_pool, page_id_t(page_id.space(), i)); - if (bpage + if (bpage != NULL && buf_page_is_accessed(bpage) && buf_page_peek_if_young(bpage)) { @@ -352,21 +357,22 @@ read_ahead: /* 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)) { + const page_id_t cur_page_id(page_id.space(), i); + + if (!ibuf_bitmap_page(cur_page_id, page_size)) { + buf_page_t* rpage = NULL; count += buf_read_page_low( &err, false, - ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, - space, zip_size, FALSE, - tablespace_version, i, NULL); + IORequest::DO_NOT_WAKE, + ibuf_mode, + cur_page_id, page_size, false, &rpage); + 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); + ib::warn() << "Random readahead trying to" + " access page " << cur_page_id + << " in nonexisting or" + " being-dropped tablespace"; + break; } } } @@ -377,14 +383,12 @@ read_ahead: 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); + if (count) { + DBUG_PRINT("ib_buf", ("random read-ahead %u pages, %u:%u", + (unsigned) count, + (unsigned) page_id.space(), + (unsigned) page_id.page_no())); } -#endif /* UNIV_DEBUG */ /* Read ahead is considered one I/O operation for the purpose of LRU policy decision. */ @@ -395,42 +399,37 @@ read_ahead: return(count); } -/********************************************************************//** -High-level function which reads a page asynchronously from a file to the +/** 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. +@param[in] page_id page id +@param[in] page_size page size @return TRUE if page has been read in, FALSE in case of failure */ -UNIV_INTERN ibool buf_read_page( -/*==========*/ - ulint space, /*!< in: space id */ - ulint zip_size,/*!< in: compressed page size in bytes, or 0 */ - ulint offset, /*!< in: page number */ + const page_id_t& page_id, + const page_size_t& page_size, buf_page_t** bpage) /*!< out: page */ { - ib_int64_t tablespace_version; ulint count; dberr_t err; - tablespace_version = fil_space_get_version(space); + /* We do synchronous IO because our AIO completion code + is sub-optimal. See buf_page_io_complete(), we have to + acquire the buffer pool mutex before acquiring the block + mutex, required for updating the page state. The acquire + of the buffer pool mutex becomes an expensive bottleneck. */ - /* We do the i/o in the synchronous aio mode to save thread - switches: hence TRUE */ + count = buf_read_page_low( + &err, true, + 0, BUF_READ_ANY_PAGE, page_id, page_size, false, bpage); - count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space, - zip_size, FALSE, - tablespace_version, offset, bpage); srv_stats.buf_pool_reads.add(count); + if (err == DB_TABLESPACE_DELETED) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: trying to access" - " tablespace %lu page no. %lu,\n" - "InnoDB: but the tablespace does not exist" - " or is just being dropped.\n", - (ulong) space, (ulong) offset); + ib::error() << "trying to read page " << page_id + << " in nonexisting or being-dropped tablespace"; } /* Increment number of I/O operations used for LRU policy. */ @@ -439,37 +438,30 @@ buf_read_page( return(count > 0); } -/********************************************************************//** -High-level function which reads a page asynchronously from a file to the +/** 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. +@param[in] page_id page id +@param[in] page_size page size +@param[in] sync true if synchronous aio is desired @return TRUE if page has been read in, FALSE in case of failure */ -UNIV_INTERN ibool -buf_read_page_async( -/*================*/ - ulint space, /*!< in: space id */ - ulint offset) /*!< in: page number */ +buf_read_page_background( + const page_id_t& page_id, + const page_size_t& page_size, + bool sync) { - ulint zip_size; - ib_int64_t tablespace_version; ulint count; dberr_t err; + buf_page_t* rbpage = NULL; - zip_size = fil_space_get_zip_size(space); + count = buf_read_page_low( + &err, sync, + IORequest::DO_NOT_WAKE | IORequest::IGNORE_MISSING, + BUF_READ_ANY_PAGE, + page_id, page_size, false, &rbpage); - if (zip_size == ULINT_UNDEFINED) { - return(FALSE); - } - - tablespace_version = fil_space_get_version(space); - - count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE - | OS_AIO_SIMULATED_WAKE_LATER - | BUF_READ_IGNORE_NONEXISTENT_PAGES, - space, zip_size, FALSE, - tablespace_version, offset, NULL); srv_stats.buf_pool_reads.add(count); /* We do not increment number of I/O operations used for LRU policy @@ -482,8 +474,7 @@ buf_read_page_async( return(count > 0); } -/********************************************************************//** -Applies linear read-ahead if in the buf_pool the page is a border page of +/** 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 algorithm looks at the 'natural' adjacent successor and @@ -505,28 +496,25 @@ latches! NOTE 3: 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 io. -@return number of page read requests issued */ -UNIV_INTERN +@param[in] page_id page id; see NOTE 3 above +@param[in] page_size page size +@param[in] inside_ibuf TRUE if we are inside ibuf routine +@return number of page read requests issued */ ulint buf_read_ahead_linear( -/*==================*/ - ulint space, /*!< in: space id */ - ulint zip_size, /*!< in: compressed page size in bytes, or 0 */ - ulint offset, /*!< in: page number; see NOTE 3 above */ - ibool inside_ibuf) /*!< in: TRUE if we are inside ibuf routine */ + const page_id_t& page_id, + const page_size_t& page_size, + ibool inside_ibuf) { - buf_pool_t* buf_pool = buf_pool_get(space, offset); - ib_int64_t tablespace_version; + buf_pool_t* buf_pool = buf_pool_get(page_id); buf_page_t* bpage; buf_frame_t* frame; buf_page_t* pred_bpage = NULL; ulint pred_offset; ulint succ_offset; - ulint count; int asc_or_desc; ulint new_offset; ulint fail_count; - ulint ibuf_mode; ulint low, high; dberr_t err; ulint i; @@ -539,24 +527,23 @@ buf_read_ahead_linear( return(0); } - if (UNIV_UNLIKELY(srv_startup_is_before_trx_rollback_phase)) { + if (srv_startup_is_before_trx_rollback_phase) { /* No read-ahead to avoid thread deadlocks */ return(0); } - low = (offset / buf_read_ahead_linear_area) + low = (page_id.page_no() / buf_read_ahead_linear_area) * buf_read_ahead_linear_area; - high = (offset / buf_read_ahead_linear_area + 1) + high = (page_id.page_no() / buf_read_ahead_linear_area + 1) * buf_read_ahead_linear_area; - if ((offset != low) && (offset != high - 1)) { + if ((page_id.page_no() != low) && (page_id.page_no() != high - 1)) { /* This is not a border page of the area: return */ return(0); } - if (ibuf_bitmap_page(zip_size, offset) - || trx_sys_hdr_page(space, offset)) { + if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) { /* If it is an ibuf bitmap page or trx sys hdr, we do no read-ahead, as that could break the ibuf page access @@ -568,18 +555,22 @@ buf_read_ahead_linear( /* 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! */ + ulint space_size; - tablespace_version = fil_space_get_version(space); - - buf_pool_mutex_enter(buf_pool); - - if (high > fil_space_get_size(space)) { - buf_pool_mutex_exit(buf_pool); - /* The area is not whole, return */ + if (fil_space_t* space = fil_space_acquire(page_id.space())) { + space_size = space->size; + fil_space_release(space); + if (high > space_size) { + /* The area is not whole */ + return(0); + } + } else { return(0); } + buf_pool_mutex_enter(buf_pool); + if (buf_pool->n_pend_reads > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) { buf_pool_mutex_exit(buf_pool); @@ -593,19 +584,20 @@ buf_read_ahead_linear( asc_or_desc = 1; - if (offset == low) { + if (page_id.page_no() == low) { asc_or_desc = -1; } /* How many out of order accessed pages can we ignore when working out the access pattern for linear readahead */ - threshold = ut_min((64 - srv_read_ahead_threshold), + threshold = ut_min(static_cast<ulint>(64 - srv_read_ahead_threshold), BUF_READ_AHEAD_AREA(buf_pool)); fail_count = 0; for (i = low; i < high; i++) { - bpage = buf_page_hash_get(buf_pool, space, i); + bpage = buf_page_hash_get(buf_pool, + page_id_t(page_id.space(), i)); if (bpage == NULL || !buf_page_is_accessed(bpage)) { /* Not accessed */ @@ -643,7 +635,7 @@ buf_read_ahead_linear( /* If we got this far, we know that enough pages in the area have been accessed in the right order: linear read-ahead can be sensible */ - bpage = buf_page_hash_get(buf_pool, space, offset); + bpage = buf_page_hash_get(buf_pool, page_id); if (bpage == NULL) { buf_pool_mutex_exit(buf_pool); @@ -674,12 +666,14 @@ buf_read_ahead_linear( buf_pool_mutex_exit(buf_pool); - if ((offset == low) && (succ_offset == offset + 1)) { + if ((page_id.page_no() == low) + && (succ_offset == page_id.page_no() + 1)) { /* This is ok, we can continue */ new_offset = pred_offset; - } else if ((offset == high - 1) && (pred_offset == offset - 1)) { + } else if ((page_id.page_no() == high - 1) + && (pred_offset == page_id.page_no() - 1)) { /* This is ok, we can continue */ new_offset = succ_offset; @@ -700,19 +694,19 @@ buf_read_ahead_linear( return(0); } - if (high > fil_space_get_size(space)) { + if (high > space_size) { /* The area is not whole, return */ return(0); } + ulint count = 0; + /* If we got this far, read-ahead can be sensible: do it */ - ibuf_mode = inside_ibuf - ? BUF_READ_IBUF_PAGES_ONLY | OS_AIO_SIMULATED_WAKE_LATER - : BUF_READ_ANY_PAGE | OS_AIO_SIMULATED_WAKE_LATER; + ulint ibuf_mode; - count = 0; + ibuf_mode = inside_ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE; /* Since Windows XP seems to schedule the i/o handler thread very eagerly, and consequently it does not wait for the @@ -724,20 +718,22 @@ buf_read_ahead_linear( /* 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)) { + const page_id_t cur_page_id(page_id.space(), i); + + if (!ibuf_bitmap_page(cur_page_id, page_size)) { + buf_page_t* rpage = NULL; + count += buf_read_page_low( &err, false, - ibuf_mode, - space, zip_size, FALSE, tablespace_version, i, NULL); + IORequest::DO_NOT_WAKE, + ibuf_mode, cur_page_id, page_size, false, &rpage); + if (err == DB_TABLESPACE_DELETED) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Warning: in" - " linear 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); + ib::warn() << "linear readahead trying to" + " access page " + << page_id_t(page_id.space(), i) + << " in nonexisting or being-dropped" + " tablespace"; } } } @@ -748,13 +744,13 @@ buf_read_ahead_linear( os_aio_simulated_wake_handler_threads(); -#ifdef UNIV_DEBUG - if (buf_debug_prints && (count > 0)) { - fprintf(stderr, - "LINEAR read-ahead space %lu offset %lu pages %lu\n", - (ulong) space, (ulong) offset, (ulong) count); + if (count) { + DBUG_PRINT("ib_buf", ("linear read-ahead %lu pages, " + UINT32PF ":" UINT32PF, + count, + page_id.space(), + page_id.page_no())); } -#endif /* UNIV_DEBUG */ /* Read ahead is considered one I/O operation for the purpose of LRU policy decision. */ @@ -768,7 +764,6 @@ buf_read_ahead_linear( Issues read requests for pages which the ibuf module wants to read in, in order to contract the insert buffer tree. Technically, this function is like a read-ahead function. */ -UNIV_INTERN void buf_read_ibuf_merge_pages( /*======================*/ @@ -778,7 +773,7 @@ buf_read_ibuf_merge_pages( to get read in, before this function returns */ const ulint* space_ids, /*!< in: array of space ids */ - const ib_int64_t* space_versions,/*!< in: the spaces must have + const ib_uint64_t* space_versions,/*!< in: the spaces must have this version number (timestamp), otherwise we discard the read; we use this @@ -792,100 +787,94 @@ buf_read_ibuf_merge_pages( ulint n_stored) /*!< in: number of elements in the arrays */ { - ulint i; - #ifdef UNIV_IBUF_DEBUG ut_a(n_stored < UNIV_PAGE_SIZE); #endif - for (i = 0; i < n_stored; i++) { - dberr_t err; - buf_pool_t* buf_pool; - ulint zip_size = fil_space_get_zip_size(space_ids[i]); + for (ulint i = 0; i < n_stored; i++) { + const page_id_t page_id(space_ids[i], page_nos[i]); + + buf_pool_t* buf_pool = buf_pool_get(page_id); + buf_page_t* rpage = NULL; - buf_pool = buf_pool_get(space_ids[i], page_nos[i]); + bool found; + const page_size_t page_size(fil_space_get_page_size( + space_ids[i], &found)); + + if (!found) { + /* The tablespace was not found, remove the + entries for that page */ + ibuf_merge_or_delete_for_page(NULL, page_id, + NULL, FALSE); + continue; + } while (buf_pool->n_pend_reads > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) { os_thread_sleep(500000); } - if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) { + dberr_t err; - goto tablespace_deleted; - } + buf_read_page_low(&err, + sync && (i + 1 == n_stored), + 0, + BUF_READ_ANY_PAGE, page_id, page_size, + true, &rpage); - buf_read_page_low(&err, sync && (i + 1 == n_stored), - BUF_READ_ANY_PAGE, space_ids[i], - zip_size, TRUE, space_versions[i], - page_nos[i], NULL); - - if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) { -tablespace_deleted: + if (err == DB_TABLESPACE_DELETED) { /* We have deleted or are deleting the single-table tablespace: remove the entries for that page */ - - ibuf_merge_or_delete_for_page(NULL, space_ids[i], - page_nos[i], - zip_size, FALSE); + ibuf_merge_or_delete_for_page(NULL, page_id, + &page_size, FALSE); } } os_aio_simulated_wake_handler_threads(); -#ifdef UNIV_DEBUG - if (buf_debug_prints) { - fprintf(stderr, - "Ibuf merge read-ahead space %lu pages %lu\n", - (ulong) space_ids[0], (ulong) n_stored); + if (n_stored) { + DBUG_PRINT("ib_buf", + ("ibuf merge read-ahead %u pages, space %u", + unsigned(n_stored), unsigned(space_ids[0]))); } -#endif /* UNIV_DEBUG */ } -/********************************************************************//** -Issues read requests for pages which recovery wants to read in. */ -UNIV_INTERN +/** Issues read requests for pages which recovery wants to read in. +@param[in] sync true if the caller wants this function to wait +for the highest address page to get read in, before this function returns +@param[in] space_id tablespace id +@param[in] page_nos array of page numbers to read, with the +highest page number the last in the array +@param[in] n_stored number of page numbers in the array */ void buf_read_recv_pages( -/*================*/ - ibool sync, /*!< in: TRUE if the caller - wants this function to wait - for the highest address page - to get read in, before this - function returns */ - ulint space, /*!< in: space id */ - ulint zip_size, /*!< in: compressed page size in - bytes, or 0 */ - const ulint* page_nos, /*!< in: array of page numbers - to read, with the highest page - number the last in the - array */ - ulint n_stored) /*!< in: number of page numbers - in the array */ + bool sync, + ulint space_id, + const ulint* page_nos, + ulint n_stored) { - ib_int64_t tablespace_version; - ulint count; - dberr_t err; - ulint i; - - zip_size = fil_space_get_zip_size(space); - - if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) { - /* It is a single table tablespace and the .ibd file is - missing: do nothing */ + ulint count; + dberr_t err; + ulint i; + fil_space_t* space = fil_space_get(space_id); + if (space == NULL) { + /* The tablespace is missing: do nothing */ return; } - tablespace_version = fil_space_get_version(space); + fil_space_open_if_needed(space); + + const page_size_t page_size(space->flags); for (i = 0; i < n_stored; i++) { - buf_pool_t* buf_pool; + buf_pool_t* buf_pool; + const page_id_t cur_page_id(space_id, page_nos[i]); + buf_page_t* rpage = NULL; count = 0; - os_aio_print_debug = FALSE; - buf_pool = buf_pool_get(space, page_nos[i]); + buf_pool = buf_pool_get(cur_page_id); while (buf_pool->n_pend_reads >= recv_n_pool_free_frames / 2) { os_aio_simulated_wake_handler_threads(); @@ -893,42 +882,34 @@ buf_read_recv_pages( count++; - if (count > 1000) { - fprintf(stderr, - "InnoDB: Error: InnoDB has waited for" - " 10 seconds for pending\n" - "InnoDB: reads to the buffer pool to" - " be finished.\n" - "InnoDB: Number of pending reads %lu," - " pending pread calls %lu\n", - (ulong) buf_pool->n_pend_reads, - (ulong) os_file_n_pending_preads); - - os_aio_print_debug = TRUE; + if (!(count % 1000)) { + + ib::error() + << "Waited for " << count / 100 + << " seconds for " + << buf_pool->n_pend_reads + << " pending reads"; } } - os_aio_print_debug = FALSE; - if ((i + 1 == n_stored) && sync) { - buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space, - zip_size, TRUE, tablespace_version, - page_nos[i], NULL); + buf_read_page_low( + &err, true, + 0, + BUF_READ_ANY_PAGE, + cur_page_id, page_size, true, &rpage); } else { - buf_read_page_low(&err, false, BUF_READ_ANY_PAGE - | OS_AIO_SIMULATED_WAKE_LATER, - space, zip_size, TRUE, - tablespace_version, page_nos[i], NULL); + buf_read_page_low( + &err, false, + IORequest::DO_NOT_WAKE, + BUF_READ_ANY_PAGE, + cur_page_id, page_size, true, &rpage); } } os_aio_simulated_wake_handler_threads(); -#ifdef UNIV_DEBUG - if (buf_debug_prints) { - fprintf(stderr, - "Recovery applies read-ahead pages %lu\n", - (ulong) n_stored); - } -#endif /* UNIV_DEBUG */ + DBUG_PRINT("ib_buf", ("recovery read-ahead (%u pages)", + unsigned(n_stored))); } + |