diff options
Diffstat (limited to 'storage/innobase/buf/buf0dblwr.cc')
-rw-r--r-- | storage/innobase/buf/buf0dblwr.cc | 161 |
1 files changed, 84 insertions, 77 deletions
diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index ad6ef7c4cef..fb853fe1543 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -25,16 +25,16 @@ Created 2011/12/19 #include "buf0dblwr.h" +#ifdef UNIV_NONINL +#include "buf0buf.ic" +#endif + #include "buf0buf.h" -#include "buf0lru.h" -#include "buf0flu.h" #include "buf0checksum.h" #include "srv0start.h" #include "srv0srv.h" #include "page0zip.h" #include "trx0sys.h" -#include "page0page.h" -#include "mtr0log.h" #ifndef UNIV_HOTBACKUP @@ -195,22 +195,20 @@ start_again: return; } - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Doublewrite buffer not found:" - " creating new\n"); + ib_logf(IB_LOG_LEVEL_INFO, + "Doublewrite buffer not found: creating new"); if (buf_pool_get_curr_size() < ((2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE + FSP_EXTENT_SIZE / 2 + 100) * UNIV_PAGE_SIZE)) { - fprintf(stderr, - "InnoDB: Cannot create doublewrite buffer:" - " you must\n" - "InnoDB: increase your buffer pool size.\n" - "InnoDB: Cannot continue operation.\n"); - exit(1); + ib_logf(IB_LOG_LEVEL_ERROR, + "Cannot create doublewrite buffer: you must " + "increase your buffer pool size. Cannot continue " + "operation."); + + exit(EXIT_FAILURE); } block2 = fseg_create(TRX_SYS_SPACE, TRX_SYS_PAGE_NO, @@ -223,16 +221,15 @@ start_again: buf_block_dbg_add_level(block2, SYNC_NO_ORDER_CHECK); if (block2 == NULL) { - fprintf(stderr, - "InnoDB: Cannot create doublewrite buffer:" - " you must\n" - "InnoDB: increase your tablespace size.\n" - "InnoDB: Cannot continue operation.\n"); + ib_logf(IB_LOG_LEVEL_ERROR, + "Cannot create doublewrite buffer: you must " + "increase your tablespace size. " + "Cannot continue operation."); /* We exit without committing the mtr to prevent its modifications to the database getting to disk */ - exit(1); + exit(EXIT_FAILURE); } fseg_header = doublewrite + TRX_SYS_DOUBLEWRITE_FSEG; @@ -243,15 +240,12 @@ start_again: new_block = fseg_alloc_free_page( fseg_header, prev_page_no + 1, FSP_UP, &mtr); if (new_block == NULL) { - fprintf(stderr, - "InnoDB: Cannot create doublewrite" - " buffer: you must\n" - "InnoDB: increase your" - " tablespace size.\n" - "InnoDB: Cannot continue operation.\n" - ); - - exit(1); + ib_logf(IB_LOG_LEVEL_ERROR, + "Cannot create doublewrite buffer: you must " + "increase your tablespace size. " + "Cannot continue operation."); + + exit(EXIT_FAILURE); } /* We read the allocated pages to the buffer pool; @@ -331,8 +325,7 @@ start_again: /* Remove doublewrite pages from LRU */ buf_pool_invalidate(); - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: Doublewrite buffer created\n"); + ib_logf(IB_LOG_LEVEL_INFO, "Doublewrite buffer created"); goto start_again; } @@ -391,7 +384,7 @@ buf_dblwr_init_or_restore_pages( } if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED) - != TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N) { + != TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N) { /* We are upgrading from a version < 4.1.x to a version where multiple tablespaces are supported. We must reset the space id @@ -401,9 +394,8 @@ buf_dblwr_init_or_restore_pages( reset_space_ids = TRUE; - fprintf(stderr, - "InnoDB: Resetting space id's in the" - " doublewrite buffer\n"); + ib_logf(IB_LOG_LEVEL_INFO, + "Resetting space id's in the doublewrite buffer"); } /* Read the pages from the doublewrite buffer to memory */ @@ -459,12 +451,11 @@ buf_dblwr_init_or_restore_pages( } else if (!fil_check_adress_in_tablespace(space_id, page_no)) { - fprintf(stderr, - "InnoDB: Warning: a page in the" - " doublewrite buffer is not within space\n" - "InnoDB: bounds; space id %lu" - " page number %lu, page %lu in" - " doublewrite buf.\n", + ib_logf(IB_LOG_LEVEL_WARN, + "A page in the doublewrite buffer is not " + "within space bounds; space id %lu " + "page number %lu, page %lu in " + "doublewrite buf.", (ulong) space_id, (ulong) page_no, (ulong) i); } else if (space_id == TRX_SYS_SPACE @@ -489,8 +480,7 @@ buf_dblwr_init_or_restore_pages( /* Check if the page is corrupt */ - if (UNIV_UNLIKELY - (buf_page_is_corrupted(read_buf, zip_size))) { + if (buf_page_is_corrupted(true, read_buf, zip_size)) { fprintf(stderr, "InnoDB: Warning: database page" @@ -501,7 +491,8 @@ buf_dblwr_init_or_restore_pages( " the doublewrite buffer.\n", (ulong) space_id, (ulong) page_no); - if (buf_page_is_corrupted(page, zip_size)) { + if (buf_page_is_corrupted(true, + page, zip_size)) { fprintf(stderr, "InnoDB: Dump of the page:\n"); buf_page_print( @@ -538,9 +529,10 @@ buf_dblwr_init_or_restore_pages( zip_size, page_no, 0, zip_size ? zip_size : UNIV_PAGE_SIZE, page, NULL); - fprintf(stderr, - "InnoDB: Recovered the page from" - " the doublewrite buffer.\n"); + + ib_logf(IB_LOG_LEVEL_INFO, + "Recovered the page from" + " the doublewrite buffer."); } } @@ -595,6 +587,7 @@ buf_dblwr_update(void) ut_ad(buf_dblwr->batch_running); ut_ad(buf_dblwr->b_reserved > 0); + ut_ad(buf_dblwr->b_reserved <= buf_dblwr->first_free); buf_dblwr->b_reserved--; if (buf_dblwr->b_reserved == 0) { @@ -705,23 +698,29 @@ static void buf_dblwr_write_block_to_datafile( /*==============================*/ - const buf_block_t* block) /*!< in: block to write */ + const buf_page_t* bpage) /*!< in: page to write */ { - ut_a(block); - ut_a(buf_page_in_file(&block->page)); + ut_a(bpage); + ut_a(buf_page_in_file(bpage)); - if (block->page.zip.data) { + /* Increment the counter of I/O operations used + for selecting LRU policy. */ + buf_LRU_stat_inc_io(); + + if (bpage->zip.data) { fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, - FALSE, buf_page_get_space(&block->page), - buf_page_get_zip_size(&block->page), - buf_page_get_page_no(&block->page), 0, - buf_page_get_zip_size(&block->page), - (void*) block->page.zip.data, - (void*) block); - - goto exit; + FALSE, buf_page_get_space(bpage), + buf_page_get_zip_size(bpage), + buf_page_get_page_no(bpage), 0, + buf_page_get_zip_size(bpage), + (void*) bpage->zip.data, + (void*) bpage); + + return; } + + const buf_block_t* block = (buf_block_t*) bpage; ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); buf_dblwr_check_page_lsn(block->frame); @@ -729,11 +728,6 @@ buf_dblwr_write_block_to_datafile( FALSE, buf_block_get_space(block), 0, buf_block_get_page_no(block), 0, UNIV_PAGE_SIZE, (void*) block->frame, (void*) block); - -exit: - /* Increment the counter of I/O operations used - for selecting LRU policy. */ - buf_LRU_stat_inc_io(); } /********************************************************************//** @@ -748,9 +742,8 @@ buf_dblwr_flush_buffered_writes(void) /*=================================*/ { byte* write_buf; + ulint first_free; ulint len; - ulint len2; - ulint i; if (!srv_use_doublewrite_buf || buf_dblwr == NULL) { /* Sync the writes to the disk. */ @@ -782,10 +775,12 @@ try_again: } ut_a(!buf_dblwr->batch_running); + ut_ad(buf_dblwr->first_free == buf_dblwr->b_reserved); /* Disallow anyone else to post to doublewrite buffer or to start another batch of flushing. */ buf_dblwr->batch_running = TRUE; + first_free = buf_dblwr->first_free; /* Now safe to release the mutex. Note that though no other thread is allowed to post to the doublewrite batch flushing @@ -795,7 +790,7 @@ try_again: write_buf = buf_dblwr->write_buf; - for (len2 = 0, i = 0; + for (ulint len2 = 0, i = 0; i < buf_dblwr->first_free; len2 += UNIV_PAGE_SIZE, i++) { @@ -845,8 +840,8 @@ try_again: flush: /* increment the doublewrite flushed pages counter */ - srv_dblwr_pages_written += buf_dblwr->first_free; - srv_dblwr_writes++; + srv_stats.dblwr_pages_written.add(buf_dblwr->first_free); + srv_stats.dblwr_writes.inc(); /* Now flush the doublewrite buffer data to disk */ fil_flush(TRX_SYS_SPACE); @@ -855,11 +850,21 @@ flush: and in recovery we will find them in the doublewrite buffer blocks. Next do the writes to the intended positions. */ - for (i = 0; i < buf_dblwr->first_free; i++) { - const buf_block_t* block = (buf_block_t*) - buf_dblwr->buf_block_arr[i]; - - buf_dblwr_write_block_to_datafile(block); + /* Up to this point first_free and buf_dblwr->first_free are + same because we have set the buf_dblwr->batch_running flag + disallowing any other thread to post any request but we + can't safely access buf_dblwr->first_free in the loop below. + This is so because it is possible that after we are done with + the last iteration and before we terminate the loop, the batch + gets finished in the IO helper thread and another thread posts + a new batch setting buf_dblwr->first_free to a higher value. + If this happens and we are using buf_dblwr->first_free in the + loop termination condition then we'll end up dispatching + the same block twice from two different threads. */ + ut_ad(first_free == buf_dblwr->first_free); + for (ulint i = 0; i < first_free; i++) { + buf_dblwr_write_block_to_datafile( + buf_dblwr->buf_block_arr[i]); } /* Wake possible simulated aio thread to actually post the @@ -935,6 +940,8 @@ try_again: buf_dblwr->first_free++; buf_dblwr->b_reserved++; + ut_ad(!buf_dblwr->batch_running); + ut_ad(buf_dblwr->first_free == buf_dblwr->b_reserved); ut_ad(buf_dblwr->b_reserved <= srv_doublewrite_batch_size); if (buf_dblwr->first_free == srv_doublewrite_batch_size) { @@ -1065,7 +1072,7 @@ retry: /* We know that the write has been flushed to disk now and during recovery we will find it in the doublewrite buffer blocks. Next do the write to the intended position. */ - buf_dblwr_write_block_to_datafile((buf_block_t*) bpage); + buf_dblwr_write_block_to_datafile(bpage); /* Sync the writes to the disk. */ buf_flush_sync_datafiles(); @@ -1077,8 +1084,8 @@ retry: buf_dblwr->in_use[i] = FALSE; /* increment the doublewrite flushed pages counter */ - srv_dblwr_pages_written += buf_dblwr->first_free; - srv_dblwr_writes++; + srv_stats.dblwr_pages_written.inc(); + srv_stats.dblwr_writes.inc(); mutex_exit(&(buf_dblwr->mutex)); |