Commit c02c329a authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-12266: Skip a lookup when checking free space

fsp_get_available_space_in_free_extents(): Declare the function static
in the only caller, and take const fil_space_t& as a parameter.
parent 330ecb90
...@@ -2815,69 +2815,6 @@ fsp_reserve_free_extents( ...@@ -2815,69 +2815,6 @@ fsp_reserve_free_extents(
return(false); return(false);
} }
/** Calculate how many KiB of new data we will be able to insert to the
tablespace without running out of space.
@param[in] space_id tablespace ID
@return available space in KiB
@retval UINTMAX_MAX if unknown */
uintmax_t
fsp_get_available_space_in_free_extents(
ulint space_id)
{
FilSpace space(space_id);
if (space() == NULL) {
return(UINTMAX_MAX);
}
return(fsp_get_available_space_in_free_extents(space));
}
/** Calculate how many KiB of new data we will be able to insert to the
tablespace without running out of space. Start with a space object that has
been acquired by the caller who holds it for the calculation,
@param[in] space tablespace object from fil_space_acquire()
@return available space in KiB */
uintmax_t
fsp_get_available_space_in_free_extents(
const fil_space_t* space)
{
ut_ad(space->n_pending_ops > 0);
ulint size_in_header = space->size_in_header;
if (size_in_header < FSP_EXTENT_SIZE) {
return(0); /* TODO: count free frag pages and
return a value based on that */
}
/* Below we play safe when counting free extents above the free limit:
some of them will contain extent descriptor pages, and therefore
will not be free extents */
ut_ad(size_in_header >= space->free_limit);
ulint n_free_up =
(size_in_header - space->free_limit) / FSP_EXTENT_SIZE;
page_size_t page_size(space->flags);
if (n_free_up > 0) {
n_free_up--;
n_free_up -= n_free_up / (page_size.physical()
/ FSP_EXTENT_SIZE);
}
/* We reserve 1 extent + 0.5 % of the space size to undo logs
and 1 extent + 0.5 % to cleaning operations; NOTE: this source
code is duplicated in the function above! */
ulint reserve = 2 + ((size_in_header / FSP_EXTENT_SIZE) * 2) / 200;
ulint n_free = space->free_len + n_free_up;
if (reserve > n_free) {
return(0);
}
return(static_cast<uintmax_t>(n_free - reserve)
* FSP_EXTENT_SIZE * (page_size.physical() / 1024));
}
/********************************************************************//** /********************************************************************//**
Marks a page used. The page must reside within the extents of the given Marks a page used. The page must reside within the extents of the given
segment. */ segment. */
......
...@@ -13823,6 +13823,50 @@ innodb_rec_per_key( ...@@ -13823,6 +13823,50 @@ innodb_rec_per_key(
return(rec_per_key); return(rec_per_key);
} }
/** Calculate how many KiB of new data we will be able to insert to the
tablespace without running out of space. Start with a space object that has
been acquired by the caller who holds it for the calculation,
@param[in] space tablespace object from fil_space_acquire()
@return available space in KiB */
static uintmax_t
fsp_get_available_space_in_free_extents(const fil_space_t& space)
{
ut_ad(space.n_pending_ops > 0);
ulint size_in_header = space.size_in_header;
if (size_in_header < FSP_EXTENT_SIZE) {
return 0; /* TODO: count free frag pages and
return a value based on that */
}
/* Below we play safe when counting free extents above the free limit:
some of them will contain extent descriptor pages, and therefore
will not be free extents */
ut_ad(size_in_header >= space.free_limit);
ulint n_free_up =
(size_in_header - space.free_limit) / FSP_EXTENT_SIZE;
const ulint size = page_size_t(space.flags).physical();
if (n_free_up > 0) {
n_free_up--;
n_free_up -= n_free_up / (size / FSP_EXTENT_SIZE);
}
/* We reserve 1 extent + 0.5 % of the space size to undo logs
and 1 extent + 0.5 % to cleaning operations; NOTE: this source
code is duplicated in the function above! */
ulint reserve = 2 + ((size_in_header / FSP_EXTENT_SIZE) * 2) / 200;
ulint n_free = space.free_len + n_free_up;
if (reserve > n_free) {
return(0);
}
return(static_cast<uintmax_t>(n_free - reserve)
* FSP_EXTENT_SIZE * (size / 1024));
}
/*********************************************************************//** /*********************************************************************//**
Returns statistics information of the table to the MySQL interpreter, Returns statistics information of the table to the MySQL interpreter,
in various fields of the handle object. in various fields of the handle object.
...@@ -13949,67 +13993,23 @@ ha_innobase::info_low( ...@@ -13949,67 +13993,23 @@ ha_innobase::info_low(
m_prebuilt->autoinc_last_value = 0; m_prebuilt->autoinc_last_value = 0;
} }
const page_size_t& page_size
= dict_table_page_size(ib_table);
stats.records = (ha_rows) n_rows; stats.records = (ha_rows) n_rows;
stats.deleted = 0; stats.deleted = 0;
stats.data_file_length if (fil_space_t* space = fil_space_acquire_silent(
= ((ulonglong) stat_clustered_index_size) ib_table->space)) {
* page_size.physical(); const ulint size = page_size_t(space->flags)
stats.index_file_length .physical();
= ((ulonglong) stat_sum_of_other_index_sizes) stats.data_file_length
* page_size.physical(); = ulonglong(stat_clustered_index_size)
* size;
/* Since fsp_get_available_space_in_free_extents() is stats.index_file_length
acquiring latches inside InnoDB, we do not call it if we = ulonglong(stat_sum_of_other_index_sizes)
are asked by MySQL to avoid locking. Another reason to * size;
avoid the call is that it uses quite a lot of CPU. stats.delete_length = 1024
See Bug#38185. */ * fsp_get_available_space_in_free_extents(
if (flag & HA_STATUS_NO_LOCK *space);
|| !(flag & HA_STATUS_VARIABLE_EXTRA)) { fil_space_release(space);
/* We do not update delete_length if no
locking is requested so the "old" value can
remain. delete_length is initialized to 0 in
the ha_statistics' constructor. Also we only
need delete_length to be set when
HA_STATUS_VARIABLE_EXTRA is set */
} else if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
/* Avoid accessing the tablespace if
innodb_crash_recovery is set to a high value. */
stats.delete_length = 0;
} else {
uintmax_t avail_space;
avail_space = fsp_get_available_space_in_free_extents(
ib_table->space);
if (avail_space == UINTMAX_MAX) {
THD* thd;
char errbuf[MYSYS_STRERROR_SIZE];
thd = ha_thd();
push_warning_printf(
thd,
Sql_condition::WARN_LEVEL_WARN,
ER_CANT_GET_STAT,
"InnoDB: Trying to get the free"
" space for table %s but its"
" tablespace has been discarded or"
" the .ibd file is missing. Setting"
" the free space to zero."
" (errno: %d - %s)",
ib_table->name.m_name, errno,
my_strerror(errbuf, sizeof(errbuf),
errno));
stats.delete_length = 0;
} else {
stats.delete_length = avail_space * 1024;
}
} }
stats.check_time = 0; stats.check_time = 0;
stats.mrr_length_per_rec= (uint)ref_length + 8; // 8 = max(sizeof(void *)); stats.mrr_length_per_rec= (uint)ref_length + 8; // 8 = max(sizeof(void *));
...@@ -14701,9 +14701,13 @@ ha_innobase::update_table_comment( ...@@ -14701,9 +14701,13 @@ ha_innobase::update_table_comment(
#define SSTR( x ) reinterpret_cast< std::ostringstream & >( \ #define SSTR( x ) reinterpret_cast< std::ostringstream & >( \
( std::ostringstream() << std::dec << x ) ).str() ( std::ostringstream() << std::dec << x ) ).str()
fk_str.append("InnoDB free: "); if (fil_space_t* space = fil_space_acquire_silent(
fk_str.append(SSTR(fsp_get_available_space_in_free_extents( m_prebuilt->table->space)) {
m_prebuilt->table->space))); fk_str.append("InnoDB free: ");
fk_str.append(SSTR(fsp_get_available_space_in_free_extents(
*space)));
fil_space_release(space);
}
fk_str.append(dict_print_info_on_foreign_keys( fk_str.append(dict_print_info_on_foreign_keys(
FALSE, m_prebuilt->trx, FALSE, m_prebuilt->trx,
......
...@@ -527,24 +527,6 @@ fsp_reserve_free_extents( ...@@ -527,24 +527,6 @@ fsp_reserve_free_extents(
mtr_t* mtr, mtr_t* mtr,
ulint n_pages = 2); ulint n_pages = 2);
/** Calculate how many KiB of new data we will be able to insert to the
tablespace without running out of space.
@param[in] space_id tablespace ID
@return available space in KiB
@retval UINTMAX_MAX if unknown */
uintmax_t
fsp_get_available_space_in_free_extents(
ulint space_id);
/** Calculate how many KiB of new data we will be able to insert to the
tablespace without running out of space. Start with a space object that has
been acquired by the caller who holds it for the calculation,
@param[in] space tablespace object from fil_space_acquire()
@return available space in KiB */
uintmax_t
fsp_get_available_space_in_free_extents(
const fil_space_t* space);
/**********************************************************************//** /**********************************************************************//**
Frees a single page of a segment. */ Frees a single page of a segment. */
void void
......
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