Commit 57ec42bc authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-23190 InnoDB data file extension is not crash-safe

When InnoDB is extending a data file, it is updating the FSP_SIZE
field in the first page of the data file.

In commit 8451e090 (MDEV-11556)
we removed a work-around for this bug and made recovery stricter,
by making it track changes to FSP_SIZE via redo log records, and
extend the data files before any changes are being applied to them.

It turns out that the function fsp_fill_free_list() is not crash-safe
with respect to this when it is initializing the change buffer bitmap
page (page 1, or generally, N*innodb_page_size+1). It uses a separate
mini-transaction that is committed (and will be written to the redo
log file) before the mini-transaction that actually extended the data
file. Hence, recovery can observe a reference to a page that is
beyond the current end of the data file.

fsp_fill_free_list(): Initialize the change buffer bitmap page in
the same mini-transaction.

The rest of the changes are fixing a bug that the use of the separate
mini-transaction was attempting to work around. Namely, we must ensure
that no other thread will access the change buffer bitmap page before
our mini-transaction has been committed and all page latches have been
released.

That is, for read-ahead as well as neighbour flushing, we must avoid
accessing pages that might not yet be durably part of the tablespace.

fil_space_t::committed_size: The size of the tablespace
as persisted by mtr_commit().

fil_space_t::max_page_number_for_io(): Limit the highest page
number for I/O batches to committed_size.

MTR_MEMO_SPACE_X_LOCK: Replaces MTR_MEMO_X_LOCK for fil_space_t::latch.

mtr_x_space_lock(): Replaces mtr_x_lock() for fil_space_t::latch.

mtr_memo_slot_release_func(): When releasing MTR_MEMO_SPACE_X_LOCK,
copy space->size to space->committed_size. In this way, read-ahead
or flushing will never be invoked on pages that do not yet exist
according to FSP_SIZE.
parent 98e2c17e
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2019, MariaDB Corporation. Copyright (c) 2013, 2020, MariaDB Corporation.
Copyright (c) 2013, 2014, Fusion-io Copyright (c) 2013, 2014, Fusion-io
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
...@@ -1241,8 +1241,11 @@ buf_flush_try_neighbors( ...@@ -1241,8 +1241,11 @@ buf_flush_try_neighbors(
/* fprintf(stderr, "Flush area: low %lu high %lu\n", low, high); */ /* fprintf(stderr, "Flush area: low %lu high %lu\n", low, high); */
#endif #endif
if (high > fil_space_get_size(space)) { if (fil_space_t *s = fil_space_acquire_for_io(space)) {
high = fil_space_get_size(space); high = s->max_page_number_for_io(high);
fil_space_release_for_io(s);
} else {
return 0;
} }
ulint count = 0; ulint count = 0;
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2017, MariaDB Corporation. Copyright (c) 2015, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -292,19 +292,22 @@ buf_read_ahead_random( ...@@ -292,19 +292,22 @@ buf_read_ahead_random(
return(0); return(0);
} }
/* Remember the tablespace version before we ask te tablespace size if (fil_space_t *s = fil_space_acquire_for_io(space)) {
below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we /* Remember the tablespace version along with the
do not try to read outside the bounds of the tablespace! */ tablespace size: if DISCARD + IMPORT changes the
actual .ibd file meanwhile, we do not try to read
outside the bounds of the tablespace! */
tablespace_version = s->tablespace_version;
tablespace_version = fil_space_get_version(space); low = (offset / buf_read_ahead_random_area)
* buf_read_ahead_random_area;
low = (offset / buf_read_ahead_random_area) high = (offset / buf_read_ahead_random_area + 1)
* buf_read_ahead_random_area; * buf_read_ahead_random_area;
high = (offset / buf_read_ahead_random_area + 1) high = s->max_page_number_for_io(high);
* buf_read_ahead_random_area;
if (high > fil_space_get_size(space)) {
high = fil_space_get_size(space); fil_space_release_for_io(s);
} else {
return 0;
} }
buf_pool_mutex_enter(buf_pool); buf_pool_mutex_enter(buf_pool);
...@@ -435,22 +438,16 @@ buf_read_page( ...@@ -435,22 +438,16 @@ buf_read_page(
ulint zip_size, ulint zip_size,
ulint offset) ulint offset)
{ {
ib_int64_t tablespace_version;
ulint count;
dberr_t err = DB_SUCCESS; dberr_t err = DB_SUCCESS;
tablespace_version = fil_space_get_version(space_id);
FilSpace space(space_id, true); FilSpace space(space_id, true);
if (space()) { if (space()) {
ulint count = buf_read_page_low(&err, /*sync=*/true,
/* We do the i/o in the synchronous aio mode to save thread BUF_READ_ANY_PAGE,
switches: hence TRUE */ space_id, zip_size, FALSE,
count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space_id, space()->tablespace_version,
zip_size, FALSE, offset);
tablespace_version, offset);
srv_stats.buf_pool_reads.add(count); srv_stats.buf_pool_reads.add(count);
} }
...@@ -619,21 +616,30 @@ buf_read_ahead_linear( ...@@ -619,21 +616,30 @@ buf_read_ahead_linear(
return(0); return(0);
} }
/* Remember the tablespace version before we ask te tablespace size uint32_t space_high_limit = 0;
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); if (fil_space_t *s = fil_space_acquire_for_io(space)) {
/* Remember the tablespace version along with the
tablespace size: if DISCARD + IMPORT changes the
actual .ibd file meanwhile, we do not try to read
outside the bounds of the tablespace! */
tablespace_version = s->tablespace_version;
buf_pool_mutex_enter(buf_pool); space_high_limit = s->max_page_number_for_io(ULINT_UNDEFINED);
if (high > fil_space_get_size(space)) { fil_space_release_for_io(s);
buf_pool_mutex_exit(buf_pool); } else {
return 0;
}
if (high > space_high_limit) {
/* The area is not whole, return */ /* The area is not whole, return */
return(0); return(0);
} }
buf_pool_mutex_enter(buf_pool);
if (buf_pool->n_pend_reads if (buf_pool->n_pend_reads
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) { > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
buf_pool_mutex_exit(buf_pool); buf_pool_mutex_exit(buf_pool);
...@@ -754,7 +760,7 @@ buf_read_ahead_linear( ...@@ -754,7 +760,7 @@ buf_read_ahead_linear(
return(0); return(0);
} }
if (high > fil_space_get_size(space)) { if (high > space_high_limit) {
/* The area is not whole, return */ /* The area is not whole, return */
return(0); return(0);
......
...@@ -676,7 +676,7 @@ fil_node_open_file( ...@@ -676,7 +676,7 @@ fil_node_open_file(
#ifdef UNIV_HOTBACKUP #ifdef UNIV_HOTBACKUP
add_size: add_size:
#endif /* UNIV_HOTBACKUP */ #endif /* UNIV_HOTBACKUP */
space->size += node->size; space->committed_size = space->size += node->size;
} }
ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(space->flags); ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(space->flags);
...@@ -1151,6 +1151,9 @@ fil_mutex_enter_and_prepare_for_io( ...@@ -1151,6 +1151,9 @@ fil_mutex_enter_and_prepare_for_io(
ut_a(success); ut_a(success);
/* InnoDB data files cannot shrink. */ /* InnoDB data files cannot shrink. */
ut_a(space->size >= size); ut_a(space->size >= size);
if (size > space->committed_size) {
space->committed_size = size;
}
/* There could be multiple concurrent I/O requests for /* There could be multiple concurrent I/O requests for
this tablespace (multiple threads trying to extend this tablespace (multiple threads trying to extend
......
This diff is collapsed.
...@@ -548,7 +548,7 @@ ibuf_init_at_db_start(void) ...@@ -548,7 +548,7 @@ ibuf_init_at_db_start(void)
mutex_enter(&ibuf_mutex); mutex_enter(&ibuf_mutex);
mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, NULL), &mtr); mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, NULL), &mtr);
header_page = ibuf_header_page_get(&mtr); header_page = ibuf_header_page_get(&mtr);
...@@ -2098,7 +2098,7 @@ ibuf_add_free_page(void) ...@@ -2098,7 +2098,7 @@ ibuf_add_free_page(void)
/* Acquire the fsp latch before the ibuf header, obeying the latching /* Acquire the fsp latch before the ibuf header, obeying the latching
order */ order */
mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr);
zip_size = fsp_flags_get_zip_size(flags); zip_size = fsp_flags_get_zip_size(flags);
header_page = ibuf_header_page_get(&mtr); header_page = ibuf_header_page_get(&mtr);
...@@ -2182,7 +2182,7 @@ ibuf_remove_free_page(void) ...@@ -2182,7 +2182,7 @@ ibuf_remove_free_page(void)
/* Acquire the fsp latch before the ibuf header, obeying the latching /* Acquire the fsp latch before the ibuf header, obeying the latching
order */ order */
mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr);
zip_size = fsp_flags_get_zip_size(flags); zip_size = fsp_flags_get_zip_size(flags);
header_page = ibuf_header_page_get(&mtr); header_page = ibuf_header_page_get(&mtr);
......
...@@ -306,6 +306,8 @@ struct fil_space_t { ...@@ -306,6 +306,8 @@ struct fil_space_t {
/*!< recovered tablespace size in pages; /*!< recovered tablespace size in pages;
0 if no size change was read from the redo log, 0 if no size change was read from the redo log,
or if the size change was implemented */ or if the size change was implemented */
/** the committed size of the tablespace in pages */
ulint committed_size;
ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags; ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags;
see fsp0fsp.h, see fsp0fsp.h,
fsp_flags_is_valid(), fsp_flags_is_valid(),
...@@ -365,6 +367,15 @@ struct fil_space_t { ...@@ -365,6 +367,15 @@ struct fil_space_t {
{ {
return stop_new_ops; return stop_new_ops;
} }
/** Clamp a page number for batched I/O, such as read-ahead.
@param offset page number limit
@return offset clamped to the tablespace size */
ulint max_page_number_for_io(ulint offset) const
{
const ulint limit= committed_size;
return limit > offset ? offset : limit;
}
}; };
/** Value of fil_space_t::magic_n */ /** Value of fil_space_t::magic_n */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc. Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2016, MariaDB Corporation Copyright (c) 2013, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -58,6 +58,7 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */ ...@@ -58,6 +58,7 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
#define MTR_MEMO_S_LOCK 55 #define MTR_MEMO_S_LOCK 55
#define MTR_MEMO_X_LOCK 56 #define MTR_MEMO_X_LOCK 56
#define MTR_MEMO_SPACE_X_LOCK 57
/** @name Log item types /** @name Log item types
The log items are declared 'byte' so that the compiler can warn if val The log items are declared 'byte' so that the compiler can warn if val
...@@ -295,6 +296,8 @@ This macro locks an rw-lock in s-mode. */ ...@@ -295,6 +296,8 @@ This macro locks an rw-lock in s-mode. */
This macro locks an rw-lock in x-mode. */ This macro locks an rw-lock in x-mode. */
#define mtr_x_lock(B, MTR) mtr_x_lock_func((B), __FILE__, __LINE__,\ #define mtr_x_lock(B, MTR) mtr_x_lock_func((B), __FILE__, __LINE__,\
(MTR)) (MTR))
#define mtr_x_space_lock(B, MTR) mtr_x_space_lock_func(B, __FILE__, __LINE__,\
MTR)
/*********************************************************************//** /*********************************************************************//**
NOTE! Use the macro above! NOTE! Use the macro above!
Locks a lock in s-mode. */ Locks a lock in s-mode. */
...@@ -317,6 +320,14 @@ mtr_x_lock_func( ...@@ -317,6 +320,14 @@ mtr_x_lock_func(
const char* file, /*!< in: file name */ const char* file, /*!< in: file name */
ulint line, /*!< in: line number */ ulint line, /*!< in: line number */
mtr_t* mtr); /*!< in: mtr */ mtr_t* mtr); /*!< in: mtr */
/** Acquire exclusive tablespace latch.
@param lock fil_space_t::latch
@param file source code file name of the caller
@param line source code line number of the caller
@param mtr mini-transaction */
inline void mtr_x_space_lock_func(rw_lock_t *lock,
const char *file, ulint line, mtr_t *mtr);
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/***************************************************//** /***************************************************//**
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -78,7 +79,7 @@ mtr_memo_push( ...@@ -78,7 +79,7 @@ mtr_memo_push(
ut_ad(object); ut_ad(object);
ut_ad(type >= MTR_MEMO_PAGE_S_FIX); ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
ut_ad(type <= MTR_MEMO_X_LOCK); ut_ad(type <= MTR_MEMO_SPACE_X_LOCK);
ut_ad(mtr); ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE); ut_ad(mtr->state == MTR_ACTIVE);
...@@ -293,4 +294,16 @@ mtr_x_lock_func( ...@@ -293,4 +294,16 @@ mtr_x_lock_func(
mtr_memo_push(mtr, lock, MTR_MEMO_X_LOCK); mtr_memo_push(mtr, lock, MTR_MEMO_X_LOCK);
} }
/** Acquire exclusive tablespace latch.
@param lock fil_space_t::latch
@param file source code file name of the caller
@param line source code line number of the caller
@param mtr mini-transaction */
inline void mtr_x_space_lock_func(rw_lock_t *lock,
const char *file, ulint line, mtr_t *mtr)
{
rw_lock_x_lock_inline(lock, 0, file, line);
mtr_memo_push(mtr, lock, MTR_MEMO_SPACE_X_LOCK);
}
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -87,6 +88,16 @@ mtr_memo_slot_release_func( ...@@ -87,6 +88,16 @@ mtr_memo_slot_release_func(
case MTR_MEMO_X_LOCK: case MTR_MEMO_X_LOCK:
rw_lock_x_unlock((rw_lock_t*) object); rw_lock_x_unlock((rw_lock_t*) object);
break; break;
case MTR_MEMO_SPACE_X_LOCK:
{
fil_space_t* space = reinterpret_cast<fil_space_t*>(
static_cast<char*>(object)
- reinterpret_cast<char*>(
&static_cast<fil_space_t*>(0)->latch));
space->committed_size = space->size;
rw_lock_x_unlock(&space->latch);
}
break;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
default: default:
ut_ad(slot->type == MTR_MEMO_MODIFY); ut_ad(slot->type == MTR_MEMO_MODIFY);
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, Google Inc. Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Percona Inc. Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2019, MariaDB Corporation. Copyright (c) 2013, 2020, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described Google, Inc. Those modifications are gratefully acknowledged and are described
...@@ -1203,6 +1203,10 @@ open_or_create_data_files( ...@@ -1203,6 +1203,10 @@ open_or_create_data_files(
} }
} }
if (fil_space_t* s = fil_space_get(0)) {
s->committed_size = s->size;
}
return(DB_SUCCESS); return(DB_SUCCESS);
} }
...@@ -1371,6 +1375,10 @@ srv_undo_tablespace_open( ...@@ -1371,6 +1375,10 @@ srv_undo_tablespace_open(
if (fil_node_create(name, (ulint) n_pages, space, FALSE)) { if (fil_node_create(name, (ulint) n_pages, space, FALSE)) {
err = DB_SUCCESS; err = DB_SUCCESS;
} }
if (fil_space_t* s = fil_space_get(space)) {
s->committed_size = n_pages;
}
} }
return(err); return(err);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -65,7 +65,7 @@ trx_rseg_header_create( ...@@ -65,7 +65,7 @@ trx_rseg_header_create(
ut_ad(mtr); ut_ad(mtr);
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL), ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
MTR_MEMO_X_LOCK)); MTR_MEMO_SPACE_X_LOCK));
/* Allocate a new file segment for the rollback segment */ /* Allocate a new file segment for the rollback segment */
block = fseg_create(space, 0, TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr); block = fseg_create(space, 0, TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr);
...@@ -310,7 +310,7 @@ trx_rseg_create(ulint space) ...@@ -310,7 +310,7 @@ trx_rseg_create(ulint space)
/* To obey the latching order, acquire the file space /* To obey the latching order, acquire the file space
x-latch before the trx_sys->mutex. */ x-latch before the trx_sys->mutex. */
mtr_x_lock(fil_space_get_latch(space, NULL), &mtr); mtr_x_space_lock(fil_space_get_latch(space, NULL), &mtr);
slot_no = trx_sysf_rseg_find_free(&mtr); slot_no = trx_sysf_rseg_find_free(&mtr);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation. Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -550,7 +550,7 @@ trx_sysf_create( ...@@ -550,7 +550,7 @@ trx_sysf_create(
then enter the kernel: we must do it in this order to conform then enter the kernel: we must do it in this order to conform
to the latching order rules. */ to the latching order rules. */
mtr_x_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), mtr); mtr_x_space_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), mtr);
/* Create the trx sys file block in a new allocated file segment */ /* Create the trx sys file block in a new allocated file segment */
block = fseg_create(TRX_SYS_SPACE, 0, TRX_SYS + TRX_SYS_FSEG_HEADER, block = fseg_create(TRX_SYS_SPACE, 0, TRX_SYS + TRX_SYS_FSEG_HEADER,
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2019, MariaDB Corporation. Copyright (c) 2013, 2020, MariaDB Corporation.
Copyright (c) 2013, 2014, Fusion-io Copyright (c) 2013, 2014, Fusion-io
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
...@@ -1297,8 +1297,11 @@ buf_flush_try_neighbors( ...@@ -1297,8 +1297,11 @@ buf_flush_try_neighbors(
/* fprintf(stderr, "Flush area: low %lu high %lu\n", low, high); */ /* fprintf(stderr, "Flush area: low %lu high %lu\n", low, high); */
if (high > fil_space_get_size(space)) { if (fil_space_t *s = fil_space_acquire_for_io(space)) {
high = fil_space_get_size(space); high = s->max_page_number_for_io(high);
fil_space_release_for_io(s);
} else {
return 0;
} }
ulint count = 0; ulint count = 0;
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2018, MariaDB Corporation. Copyright (c) 2013, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -344,19 +344,22 @@ buf_read_ahead_random( ...@@ -344,19 +344,22 @@ buf_read_ahead_random(
return(0); return(0);
} }
/* Remember the tablespace version before we ask te tablespace size if (fil_space_t *s = fil_space_acquire_for_io(space)) {
below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we /* Remember the tablespace version along with the
do not try to read outside the bounds of the tablespace! */ tablespace size: if DISCARD + IMPORT changes the
actual .ibd file meanwhile, we do not try to read
outside the bounds of the tablespace! */
tablespace_version = s->tablespace_version;
tablespace_version = fil_space_get_version(space); low = (offset / buf_read_ahead_random_area)
* buf_read_ahead_random_area;
low = (offset / buf_read_ahead_random_area) high = (offset / buf_read_ahead_random_area + 1)
* buf_read_ahead_random_area; * buf_read_ahead_random_area;
high = (offset / buf_read_ahead_random_area + 1) high = s->max_page_number_for_io(high);
* buf_read_ahead_random_area;
if (high > fil_space_get_size(space)) {
high = fil_space_get_size(space); fil_space_release_for_io(s);
} else {
return 0;
} }
if (buf_pool->n_pend_reads if (buf_pool->n_pend_reads
...@@ -495,22 +498,16 @@ buf_read_page( ...@@ -495,22 +498,16 @@ buf_read_page(
ulint offset, ulint offset,
trx_t* trx) trx_t* trx)
{ {
ib_int64_t tablespace_version;
ulint count;
dberr_t err = DB_SUCCESS; dberr_t err = DB_SUCCESS;
tablespace_version = fil_space_get_version(space_id);
FilSpace space(space_id, true); FilSpace space(space_id, true);
if (space()) { if (space()) {
ulint count = buf_read_page_low(&err, /*sync=*/true,
/* We do the i/o in the synchronous aio mode to save thread BUF_READ_ANY_PAGE,
switches: hence TRUE */ space_id, zip_size, FALSE,
count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space_id, space()->tablespace_version,
zip_size, FALSE, offset, trx);
tablespace_version, offset, trx);
srv_stats.buf_pool_reads.add(count); srv_stats.buf_pool_reads.add(count);
} }
...@@ -683,13 +680,23 @@ buf_read_ahead_linear( ...@@ -683,13 +680,23 @@ buf_read_ahead_linear(
return(0); return(0);
} }
/* Remember the tablespace version before we ask te tablespace size uint32_t space_high_limit = 0;
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); if (fil_space_t *s = fil_space_acquire_for_io(space)) {
/* Remember the tablespace version along with the
tablespace size: if DISCARD + IMPORT changes the
actual .ibd file meanwhile, we do not try to read
outside the bounds of the tablespace! */
tablespace_version = s->tablespace_version;
space_high_limit = s->max_page_number_for_io(ULINT_UNDEFINED);
fil_space_release_for_io(s);
} else {
return 0;
}
if (high > fil_space_get_size(space)) { if (high > space_high_limit) {
/* The area is not whole, return */ /* The area is not whole, return */
return(0); return(0);
...@@ -825,7 +832,7 @@ buf_read_ahead_linear( ...@@ -825,7 +832,7 @@ buf_read_ahead_linear(
return(0); return(0);
} }
if (high > fil_space_get_size(space)) { if (high > space_high_limit) {
/* The area is not whole, return */ /* The area is not whole, return */
return(0); return(0);
......
...@@ -684,7 +684,7 @@ fil_node_open_file( ...@@ -684,7 +684,7 @@ fil_node_open_file(
#ifdef UNIV_HOTBACKUP #ifdef UNIV_HOTBACKUP
add_size: add_size:
#endif /* UNIV_HOTBACKUP */ #endif /* UNIV_HOTBACKUP */
space->size += node->size; space->committed_size = space->size += node->size;
} }
ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(space->flags); ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(space->flags);
...@@ -1158,6 +1158,9 @@ fil_mutex_enter_and_prepare_for_io( ...@@ -1158,6 +1158,9 @@ fil_mutex_enter_and_prepare_for_io(
ut_a(success); ut_a(success);
/* InnoDB data files cannot shrink. */ /* InnoDB data files cannot shrink. */
ut_a(space->size >= size); ut_a(space->size >= size);
if (size > space->committed_size) {
space->committed_size = size;
}
/* There could be multiple concurrent I/O requests for /* There could be multiple concurrent I/O requests for
this tablespace (multiple threads trying to extend this tablespace (multiple threads trying to extend
......
This diff is collapsed.
...@@ -588,7 +588,7 @@ ibuf_init_at_db_start(void) ...@@ -588,7 +588,7 @@ ibuf_init_at_db_start(void)
mutex_enter(&ibuf_mutex); mutex_enter(&ibuf_mutex);
mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, NULL), &mtr); mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, NULL), &mtr);
header_page = ibuf_header_page_get(&mtr); header_page = ibuf_header_page_get(&mtr);
...@@ -2139,7 +2139,7 @@ ibuf_add_free_page(void) ...@@ -2139,7 +2139,7 @@ ibuf_add_free_page(void)
/* Acquire the fsp latch before the ibuf header, obeying the latching /* Acquire the fsp latch before the ibuf header, obeying the latching
order */ order */
mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr);
zip_size = fsp_flags_get_zip_size(flags); zip_size = fsp_flags_get_zip_size(flags);
header_page = ibuf_header_page_get(&mtr); header_page = ibuf_header_page_get(&mtr);
...@@ -2223,7 +2223,7 @@ ibuf_remove_free_page(void) ...@@ -2223,7 +2223,7 @@ ibuf_remove_free_page(void)
/* Acquire the fsp latch before the ibuf header, obeying the latching /* Acquire the fsp latch before the ibuf header, obeying the latching
order */ order */
mtr_x_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr); mtr_x_space_lock(fil_space_get_latch(IBUF_SPACE_ID, &flags), &mtr);
zip_size = fsp_flags_get_zip_size(flags); zip_size = fsp_flags_get_zip_size(flags);
header_page = ibuf_header_page_get(&mtr); header_page = ibuf_header_page_get(&mtr);
......
...@@ -300,6 +300,8 @@ struct fil_space_t { ...@@ -300,6 +300,8 @@ struct fil_space_t {
/*!< recovered tablespace size in pages; /*!< recovered tablespace size in pages;
0 if no size change was read from the redo log, 0 if no size change was read from the redo log,
or if the size change was implemented */ or if the size change was implemented */
/** the committed size of the tablespace in pages */
ulint committed_size;
ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags; ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags;
see fsp0fsp.h, see fsp0fsp.h,
fsp_flags_is_valid(), fsp_flags_is_valid(),
...@@ -364,6 +366,15 @@ struct fil_space_t { ...@@ -364,6 +366,15 @@ struct fil_space_t {
{ {
return stop_new_ops; return stop_new_ops;
} }
/** Clamp a page number for batched I/O, such as read-ahead.
@param offset page number limit
@return offset clamped to the tablespace size */
ulint max_page_number_for_io(ulint offset) const
{
const ulint limit= committed_size;
return limit > offset ? offset : limit;
}
}; };
/** Value of fil_space_t::magic_n */ /** Value of fil_space_t::magic_n */
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc. Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -57,6 +58,7 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */ ...@@ -57,6 +58,7 @@ first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
#define MTR_MEMO_S_LOCK 55 #define MTR_MEMO_S_LOCK 55
#define MTR_MEMO_X_LOCK 56 #define MTR_MEMO_X_LOCK 56
#define MTR_MEMO_SPACE_X_LOCK 57
/** @name Log item types /** @name Log item types
The log items are declared 'byte' so that the compiler can warn if val The log items are declared 'byte' so that the compiler can warn if val
...@@ -293,6 +295,8 @@ This macro locks an rw-lock in s-mode. */ ...@@ -293,6 +295,8 @@ This macro locks an rw-lock in s-mode. */
This macro locks an rw-lock in x-mode. */ This macro locks an rw-lock in x-mode. */
#define mtr_x_lock(B, MTR) mtr_x_lock_func((B), __FILE__, __LINE__,\ #define mtr_x_lock(B, MTR) mtr_x_lock_func((B), __FILE__, __LINE__,\
(MTR)) (MTR))
#define mtr_x_space_lock(B, MTR) mtr_x_space_lock_func(B, __FILE__, __LINE__,\
MTR)
/*********************************************************************//** /*********************************************************************//**
NOTE! Use the macro above! NOTE! Use the macro above!
Locks a lock in s-mode. */ Locks a lock in s-mode. */
...@@ -315,6 +319,14 @@ mtr_x_lock_func( ...@@ -315,6 +319,14 @@ mtr_x_lock_func(
const char* file, /*!< in: file name */ const char* file, /*!< in: file name */
ulint line, /*!< in: line number */ ulint line, /*!< in: line number */
mtr_t* mtr); /*!< in: mtr */ mtr_t* mtr); /*!< in: mtr */
/** Acquire exclusive tablespace latch.
@param lock fil_space_t::latch
@param file source code file name of the caller
@param line source code line number of the caller
@param mtr mini-transaction */
inline void mtr_x_space_lock_func(prio_rw_lock_t *lock,
const char *file, ulint line, mtr_t *mtr);
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/***************************************************//** /***************************************************//**
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -78,7 +79,7 @@ mtr_memo_push( ...@@ -78,7 +79,7 @@ mtr_memo_push(
ut_ad(object); ut_ad(object);
ut_ad(type >= MTR_MEMO_PAGE_S_FIX); ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
ut_ad(type <= MTR_MEMO_X_LOCK); ut_ad(type <= MTR_MEMO_SPACE_X_LOCK);
ut_ad(mtr); ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N); ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE); ut_ad(mtr->state == MTR_ACTIVE);
...@@ -293,4 +294,16 @@ mtr_x_lock_func( ...@@ -293,4 +294,16 @@ mtr_x_lock_func(
mtr_memo_push(mtr, lock, MTR_MEMO_X_LOCK); mtr_memo_push(mtr, lock, MTR_MEMO_X_LOCK);
} }
/** Acquire exclusive tablespace latch.
@param lock fil_space_t::latch
@param file source code file name of the caller
@param line source code line number of the caller
@param mtr mini-transaction */
inline void mtr_x_space_lock_func(prio_rw_lock_t *lock,
const char *file, ulint line, mtr_t *mtr)
{
rw_lock_x_lock_inline(lock, 0, file, line);
mtr_memo_push(mtr, lock, MTR_MEMO_SPACE_X_LOCK);
}
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -88,6 +89,16 @@ mtr_memo_slot_release_func( ...@@ -88,6 +89,16 @@ mtr_memo_slot_release_func(
case MTR_MEMO_X_LOCK: case MTR_MEMO_X_LOCK:
rw_lock_x_unlock((prio_rw_lock_t*) object); rw_lock_x_unlock((prio_rw_lock_t*) object);
break; break;
case MTR_MEMO_SPACE_X_LOCK:
{
fil_space_t* space = reinterpret_cast<fil_space_t*>(
static_cast<char*>(object)
- reinterpret_cast<char*>(
&static_cast<fil_space_t*>(0)->latch));
space->committed_size = space->size;
rw_lock_x_unlock(&space->latch);
}
break;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
default: default:
ut_ad(slot->type == MTR_MEMO_MODIFY); ut_ad(slot->type == MTR_MEMO_MODIFY);
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, Google Inc. Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Percona Inc. Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2019, MariaDB Corporation. Copyright (c) 2013, 2020, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described Google, Inc. Those modifications are gratefully acknowledged and are described
...@@ -1240,6 +1240,10 @@ open_or_create_data_files( ...@@ -1240,6 +1240,10 @@ open_or_create_data_files(
} }
} }
if (fil_space_t* s = fil_space_get(0)) {
s->committed_size = s->size;
}
return(DB_SUCCESS); return(DB_SUCCESS);
} }
...@@ -1408,6 +1412,10 @@ srv_undo_tablespace_open( ...@@ -1408,6 +1412,10 @@ srv_undo_tablespace_open(
if (fil_node_create(name, (ulint) n_pages, space, FALSE)) { if (fil_node_create(name, (ulint) n_pages, space, FALSE)) {
err = DB_SUCCESS; err = DB_SUCCESS;
} }
if (fil_space_t* s = fil_space_get(space)) {
s->committed_size = n_pages;
}
} }
return(err); return(err);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -65,7 +65,7 @@ trx_rseg_header_create( ...@@ -65,7 +65,7 @@ trx_rseg_header_create(
ut_ad(mtr); ut_ad(mtr);
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL), ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
MTR_MEMO_X_LOCK)); MTR_MEMO_SPACE_X_LOCK));
/* Allocate a new file segment for the rollback segment */ /* Allocate a new file segment for the rollback segment */
block = fseg_create(space, 0, TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr); block = fseg_create(space, 0, TRX_RSEG + TRX_RSEG_FSEG_HEADER, mtr);
...@@ -312,7 +312,7 @@ trx_rseg_create(ulint space) ...@@ -312,7 +312,7 @@ trx_rseg_create(ulint space)
/* To obey the latching order, acquire the file space /* To obey the latching order, acquire the file space
x-latch before the trx_sys->mutex. */ x-latch before the trx_sys->mutex. */
mtr_x_lock(fil_space_get_latch(space, NULL), &mtr); mtr_x_space_lock(fil_space_get_latch(space, NULL), &mtr);
slot_no = trx_sysf_rseg_find_free(&mtr); slot_no = trx_sysf_rseg_find_free(&mtr);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation. Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -554,7 +554,7 @@ trx_sysf_create( ...@@ -554,7 +554,7 @@ trx_sysf_create(
then enter the kernel: we must do it in this order to conform then enter the kernel: we must do it in this order to conform
to the latching order rules. */ to the latching order rules. */
mtr_x_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), mtr); mtr_x_space_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), mtr);
/* Create the trx sys file block in a new allocated file segment */ /* Create the trx sys file block in a new allocated file segment */
block = fseg_create(TRX_SYS_SPACE, 0, TRX_SYS + TRX_SYS_FSEG_HEADER, block = fseg_create(TRX_SYS_SPACE, 0, TRX_SYS + TRX_SYS_FSEG_HEADER,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment