Commit c507678b authored by Thirunarayanan Balathandayuthapani's avatar Thirunarayanan Balathandayuthapani Committed by Marko Mäkelä

MDEV-28699 Shrink temporary tablespaces without restart

- Introduced the variable "innodb_truncate_temporary_tablespace_now"
to shrink the temporary tablespace.

Steps for shrinking the temporary tablespace:

1) Find the last used extent in temporary tablespace
by iterating through the BITMAP in extent descriptor pages

2) If the last used extent is lesser than user specified size
then set desired target size to user specified size

3) Store the page contents of "to be modified" extent
descriptor pages, latches the "to be modified" extent
descriptor pages and check for buffer pool memory availability

4) Update the FSP_SIZE and FSP_FREE_LIMIT in header page

5) Remove the "to be truncated" pages from FSP_FREE and
FSP_FREE_FRAG list

6) Reset the bitmap in the last descriptor pages for the
"to be truncated" pages.

7) Clear the freed range in temporary tablespace which
are to be truncated.

8) Evict the "to be truncated" temporary tablespace pages
from LRU list.

9) In case of multiple files, calculate the truncated last
file size and do truncation in last file

10) Commit the mini-transaction for shrinking the tablespace
parent 7b842f15
# restart
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
f2 INT NOT NULL)ENGINE=InnoDB;
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
DROP TABLE t1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
NAME FILE_SIZE
innodb_temporary 72351744
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 0;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
NAME FILE_SIZE
innodb_temporary 72351744
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
NAME FILE_SIZE
innodb_temporary 5242880
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
f2 INT NOT NULL)ENGINE=InnoDB;
BEGIN;
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
connect con1,localhost,root,,,;
CREATE TEMPORARY TABLE t2(f1 INT NOT NULL,
f2 INT NOT NULL)ENGINE=InnoDB;
INSERT INTO t2 SELECT seq, seq FROM seq_1_to_65536;
DROP TABLE t2;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
NAME FILE_SIZE
innodb_temporary 72351744
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
NAME FILE_SIZE
innodb_temporary 7340032
connection default;
COMMIT;
SELECT COUNT(*) FROM t1;
COUNT(*)
65536
DROP TABLE t1;
call mtr.add_suppression("InnoDB: Cannot shrink the temporary tablespace");
# restart
SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=2;
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
f2 INT NOT NULL)ENGINE=InnoDB;
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
DROP TABLE t1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
NAME FILE_SIZE
innodb_temporary 1146093568
SET @saved_debug_dbug = @@SESSION.debug_dbug;
SET DEBUG_DBUG="+d,fail_temp_truncate";
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
NAME FILE_SIZE
innodb_temporary 1146093568
SET DEBUG_DBUG=@saved_debug_dbug;
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
NAME FILE_SIZE
innodb_temporary 5242880
SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=default;
--innodb_temp_data_file_path=ibtmp1:5M:autoextend
--innodb_sys_tablespaces
--source include/have_innodb.inc
--source include/have_sequence.inc
--source include/restart_mysqld.inc
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
f2 INT NOT NULL)ENGINE=InnoDB;
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
DROP TABLE t1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 0;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
# Concurrent session has open transaction for temporary tables
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
f2 INT NOT NULL)ENGINE=InnoDB;
BEGIN;
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
# Concurrent session has open transaction for temporary tables
connect(con1,localhost,root,,,);
CREATE TEMPORARY TABLE t2(f1 INT NOT NULL,
f2 INT NOT NULL)ENGINE=InnoDB;
INSERT INTO t2 SELECT seq, seq FROM seq_1_to_65536;
DROP TABLE t2;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
connection default;
COMMIT;
SELECT COUNT(*) FROM t1;
DROP TABLE t1;
--innodb_temp_data_file_path=ibtmp1:5M:autoextend
--innodb_sys_tablespaces
--source include/have_innodb.inc
--source include/have_sequence.inc
--source include/have_debug.inc
call mtr.add_suppression("InnoDB: Cannot shrink the temporary tablespace");
--source include/restart_mysqld.inc
SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=2;
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
f2 INT NOT NULL)ENGINE=InnoDB;
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
DROP TABLE t1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
SET @saved_debug_dbug = @@SESSION.debug_dbug;
SET DEBUG_DBUG="+d,fail_temp_truncate";
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
SET DEBUG_DBUG=@saved_debug_dbug;
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=default;
......@@ -1531,6 +1531,18 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW
SESSION_VALUE NULL
DEFAULT_VALUE OFF
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Shrink the temporary tablespace
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_TRX_PURGE_VIEW_UPDATE_ONLY_DEBUG
SESSION_VALUE NULL
DEFAULT_VALUE OFF
......
......@@ -1330,6 +1330,51 @@ bool buf_LRU_scan_and_free_block(ulint limit)
buf_LRU_free_from_common_LRU_list(limit);
}
void buf_LRU_truncate_temp(uint32_t threshold)
{
/* Set the extent descriptor page state as FREED */
for (uint32_t cur_xdes_page= xdes_calc_descriptor_page(
0, fil_system.temp_space->free_limit);
cur_xdes_page >= threshold;)
{
mtr_t mtr;
mtr.start();
if (buf_block_t* block= buf_page_get_gen(
page_id_t(SRV_TMP_SPACE_ID, cur_xdes_page), 0, RW_X_LATCH,
nullptr, BUF_PEEK_IF_IN_POOL, &mtr))
{
uint32_t state= block->page.state();
ut_ad(state > buf_page_t::UNFIXED);
ut_ad(state < buf_page_t::READ_FIX);
block->page.set_freed(state);
}
cur_xdes_page-= uint32_t(srv_page_size);
mtr.commit();
}
const page_id_t limit{SRV_TMP_SPACE_ID, threshold};
mysql_mutex_lock(&buf_pool.mutex);
for (buf_page_t* bpage = UT_LIST_GET_FIRST(buf_pool.LRU);
bpage;)
{
buf_page_t* next= UT_LIST_GET_NEXT(LRU, bpage);
if (bpage->id() >= limit)
{
#ifdef UNIV_DEBUG
if (bpage->lock.u_lock_try(0))
{
ut_ad(bpage->state() == buf_page_t::FREED);
bpage->lock.u_unlock();
}
#endif /* UNIV_DEBUG */
ut_ad(!reinterpret_cast<buf_block_t*>(bpage)->index);
buf_LRU_free_page(bpage, true);
}
bpage= next;
}
mysql_mutex_unlock(&buf_pool.mutex);
}
#ifdef UNIV_DEBUG
/** Validate the LRU list. */
void buf_LRU_validate()
......
......@@ -3076,21 +3076,21 @@ std::ostream &fseg_header::to_stream(std::ostream &out) const
/** Get the latched extent descriptor page or
acquire the extent descriptor page.
@param page_no page number to be acquired
@param page_id page identifier to be acquired
@param mtr mini-transaction
@param err error code
@return block descriptor */
static
buf_block_t *fsp_get_latched_xdes_page(
uint32_t page_no, mtr_t *mtr, dberr_t *err)
page_id_t page_id, mtr_t *mtr, dberr_t *err)
{
buf_block_t *block= nullptr;
block= mtr->get_already_latched(
page_id_t{0, page_no}, MTR_MEMO_PAGE_SX_FIX);
page_id, MTR_MEMO_PAGE_SX_FIX);
if (block)
return block;
return buf_page_get_gen(
page_id_t{0, page_no}, 0, RW_SX_LATCH, nullptr,
page_id, 0, RW_SX_LATCH, nullptr,
BUF_GET_POSSIBLY_FREED, mtr, err);
}
......@@ -3100,7 +3100,9 @@ old page state */
class fsp_xdes_old_page
{
std::vector<buf_block_t*> m_old_xdes_pages;
const uint32_t m_space;
public:
fsp_xdes_old_page(uint32_t space):m_space(space) {}
ulint n_pages()
{
uint32_t count=0;
......@@ -3120,7 +3122,8 @@ class fsp_xdes_old_page
DBUG_EXECUTE_IF("shrink_buffer_pool_full",
return DB_OUT_OF_MEMORY;);
dberr_t err= DB_SUCCESS;
buf_block_t *block= fsp_get_latched_xdes_page(page_no, mtr, &err);
buf_block_t *block= fsp_get_latched_xdes_page(
page_id_t(m_space, page_no), mtr, &err);
if (block)
{
buf_block_t *old= buf_LRU_get_free_block(have_no_mutex_soft);
......@@ -3150,7 +3153,7 @@ class fsp_xdes_old_page
{
if (m_old_xdes_pages[i] == nullptr) continue;
buf_block_t *block= mtr->get_already_latched(
page_id_t{0, i << srv_page_size_shift},
page_id_t{m_space, i << srv_page_size_shift},
MTR_MEMO_PAGE_SX_FIX);
ut_ad(block);
memcpy_aligned<UNIV_PAGE_SIZE_MIN>(
......@@ -3158,7 +3161,6 @@ class fsp_xdes_old_page
}
}
fsp_xdes_old_page()=default;
~fsp_xdes_old_page()
{
for (uint32_t i= 0; i < m_old_xdes_pages.size(); i++)
......@@ -3184,8 +3186,9 @@ dberr_t fsp_lst_update_skip(
uint32_t skip_len, mtr_t *mtr)
{
dberr_t err= DB_SUCCESS;
uint32_t space_id= header->page.id().space();
buf_block_t *cur= fsp_get_latched_xdes_page(
cur_addr.page, mtr, &err);
page_id_t(space_id, cur_addr.page), mtr, &err);
if (!cur) return err;
if (last_valid_addr.page == FIL_NULL)
......@@ -3212,7 +3215,8 @@ dberr_t fsp_lst_update_skip(
else
{
prev= fsp_get_latched_xdes_page(
last_valid_addr.page, mtr, &err);
page_id_t(space_id, last_valid_addr.page),
mtr, &err);
if (!prev) return err;
}
......@@ -3294,7 +3298,8 @@ fsp_lst_write_end(
cur_addr.page, cur_addr.boffset, mtr);
buf_block_t *cur_block= fsp_get_latched_xdes_page(
cur_addr.page, mtr, &err);
page_id_t(header->page.id().space(), cur_addr.page),
mtr, &err);
if (!cur_block) return err;
......@@ -3335,12 +3340,15 @@ dberr_t fsp_shrink_list(buf_block_t *header, uint16_t hdr_offset,
for (uint32_t i= len; i > 0; i--)
{
ut_ad(addr.page < fil_system.sys_space->size);
ut_d(fil_space_t *space= header->page.id().space() == 0
? fil_system.sys_space
: fil_system.temp_space);
ut_ad(addr.page < space->size);
ut_ad(!(addr.page & (srv_page_size - 1)));
if (!descr_block || descr_block->page.id().page_no() != addr.page)
{
descr_block= fsp_get_latched_xdes_page(
addr.page, mtr, &err);
page_id_t(header->page.id().space(), addr.page), mtr, &err);
if (!descr_block)
return err;
}
......@@ -3390,7 +3398,7 @@ dberr_t fsp_shrink_list(buf_block_t *header, uint16_t hdr_offset,
@return DB_SUCCESS or error code on failure */
__attribute__((warn_unused_result))
static
dberr_t fsp_xdes_reset(fil_space_t *space, uint32_t threshold, mtr_t *mtr)
dberr_t fsp_xdes_reset(uint32_t space_id, uint32_t threshold, mtr_t *mtr)
{
if (!(threshold & (srv_page_size - 1)))
return DB_SUCCESS;
......@@ -3404,7 +3412,7 @@ dberr_t fsp_xdes_reset(fil_space_t *space, uint32_t threshold, mtr_t *mtr)
last_descr_offset+= XDES_SIZE;
dberr_t err= DB_SUCCESS;
buf_block_t *block= fsp_get_latched_xdes_page(
cur_descr_page, mtr, &err);
page_id_t(space_id, cur_descr_page), mtr, &err);
if (!block)
return err;
mtr->memset(
......@@ -3455,7 +3463,9 @@ dberr_t fsp_traverse_extents(
{
if (!block)
{
block= fsp_get_latched_xdes_page(last_descr_page_no, mtr, &err);
block= fsp_get_latched_xdes_page(
page_id_t(space->id, last_descr_page_no),
mtr, &err);
if (!block) return err;
}
......@@ -3479,14 +3489,14 @@ dberr_t fsp_traverse_extents(
{
fil_addr_t prev_addr= flst_get_prev_addr(
descr + XDES_FLST_NODE);
ut_ad(prev_addr.page < fil_system.sys_space->size ||
ut_ad(prev_addr.page < space->size ||
prev_addr.page == FIL_NULL);
ut_ad(prev_addr.page == FIL_NULL ||
!(prev_addr.page & (srv_page_size - 1)));
fil_addr_t next_addr= flst_get_next_addr(
descr + XDES_FLST_NODE);
ut_ad(next_addr.page < fil_system.sys_space->size ||
ut_ad(next_addr.page < space->size ||
next_addr.page == FIL_NULL);
ut_ad(next_addr.page == FIL_NULL ||
!(next_addr.page & (srv_page_size - 1)));
......@@ -3524,14 +3534,14 @@ dberr_t fsp_traverse_extents(
#ifdef UNIV_DEBUG
/** Validate the system tablespace list */
__attribute__((warn_unused_result))
dberr_t fsp_sys_tablespace_validate()
dberr_t fsp_tablespace_validate(fil_space_t *space)
{
/* Validate all FSP list in system tablespace */
mtr_t local_mtr;
dberr_t err= DB_SUCCESS;
local_mtr.start();
if (buf_block_t *header= fsp_get_header(
fil_system.sys_space, &local_mtr, &err))
space, &local_mtr, &err))
{
flst_validate(header, FSP_FREE + FSP_HEADER_OFFSET, &local_mtr);
flst_validate(header, FSP_FREE_FRAG + FSP_HEADER_OFFSET,
......@@ -3584,7 +3594,7 @@ void fsp_system_tablespace_truncate()
srv_use_doublewrite_buf= false;
buf_block_t *header= nullptr;
ut_ad(!fsp_sys_tablespace_validate());
ut_ad(!fsp_tablespace_validate(space));
mtr.start();
mtr.x_lock_space(space);
......@@ -3592,7 +3602,7 @@ void fsp_system_tablespace_truncate()
{
/* Take the rough estimation of modified extent
descriptor page and store their old state */
fsp_xdes_old_page old_xdes_list;
fsp_xdes_old_page old_xdes_list(space->id);
err= fsp_traverse_extents(space, &last_used_extent, &mtr, &old_xdes_list);
if (err == DB_OUT_OF_MEMORY)
......@@ -3610,7 +3620,8 @@ void fsp_system_tablespace_truncate()
UINT32PF " to " UINT32PF " pages", space->size,
last_used_extent);
header= fsp_get_latched_xdes_page(0, &mtr, &err);
header= fsp_get_latched_xdes_page(
page_id_t(space->id, 0), &mtr, &err);
if (!header)
goto func_exit;
......@@ -3632,7 +3643,7 @@ void fsp_system_tablespace_truncate()
if (err != DB_SUCCESS)
goto func_exit;
err= fsp_xdes_reset(space, last_used_extent, &mtr);
err= fsp_xdes_reset(space->id, last_used_extent, &mtr);
if (err != DB_SUCCESS)
goto func_exit;
......@@ -3651,7 +3662,7 @@ void fsp_system_tablespace_truncate()
old_xdes_list.restore(&mtr);
mtr.discard_modifications();
mtr.commit();
ut_ad(!fsp_sys_tablespace_validate());
ut_ad(!fsp_tablespace_validate(space));
sql_print_error(
"InnoDB: Cannot shrink the system tablespace "
"because the mini-transaction log size (%zu bytes) "
......@@ -3684,3 +3695,119 @@ void fsp_system_tablespace_truncate()
sql_print_information("InnoDB: System tablespace truncated successfully");
srv_use_doublewrite_buf= old_dblwr_buf;
}
inline void fil_space_t::clear_freed_ranges(uint32_t threshold)
{
ut_ad(id == SRV_TMP_SPACE_ID);
std::lock_guard<std::mutex> freed_lock(freed_range_mutex);
range_set current_ranges;
for (const auto &range : freed_ranges)
{
if (range.first >= threshold)
continue;
else if (range.last > threshold)
{
range_t new_range{range.first, threshold - 1};
current_ranges.add_range(new_range);
continue;
}
current_ranges.add_range(range);
}
freed_ranges= std::move(current_ranges);
}
void fsp_shrink_temp_space()
{
uint32_t last_used_extent= 0;
fil_space_t *space= fil_system.temp_space;
mtr_t mtr;
mtr.start();
mtr.set_log_mode(MTR_LOG_NO_REDO);
mtr.x_lock_space(space);
dberr_t err= fsp_traverse_extents(space, &last_used_extent, &mtr);
if (err != DB_SUCCESS)
{
func_exit:
sql_print_warning("InnoDB: Cannot shrink the temporary tablespace "
"due to %s", ut_strerr(err));
mtr.commit();
return;
}
uint32_t fixed_size= srv_tmp_space.get_min_size(),
header_size= space->size_in_header;
if (last_used_extent >= header_size || fixed_size >= header_size)
{
/* Tablespace is being used within fixed size */
mtr.commit();
return;
}
/* Set fixed size as threshold to truncate */
if (fixed_size > last_used_extent)
last_used_extent= fixed_size;
sql_print_information("InnoDB: Truncating temporary tablespace from "
UINT32PF " to " UINT32PF " pages", space->size,
last_used_extent);
buf_block_t *header= fsp_get_latched_xdes_page(
page_id_t(space->id, 0), &mtr, &err);
if (!header)
goto func_exit;
mach_write_to_4(
FSP_HEADER_OFFSET + FSP_SIZE + header->page.frame,
last_used_extent);
if (space->free_limit > last_used_extent)
mach_write_to_4(
FSP_HEADER_OFFSET + FSP_FREE_LIMIT + header->page.frame,
last_used_extent);
mtr.set_modified(*header);
err= fsp_shrink_list(header, FSP_HEADER_OFFSET + FSP_FREE,
last_used_extent, &mtr);
if (err != DB_SUCCESS)
goto func_exit;
err= fsp_shrink_list(
header, FSP_HEADER_OFFSET + FSP_FREE_FRAG,
last_used_extent, &mtr);
DBUG_EXECUTE_IF("fail_temp_truncate", err= DB_ERROR;);
if (err != DB_SUCCESS)
goto func_exit;
err= fsp_xdes_reset(space->id, last_used_extent, &mtr);
if (err != DB_SUCCESS)
goto func_exit;
space->clear_freed_ranges(last_used_extent);
buf_LRU_truncate_temp(last_used_extent);
mysql_mutex_lock(&fil_system.mutex);
space->size= last_used_extent;
if (space->free_limit > last_used_extent)
space->free_limit= space->size;
space->free_len= flst_get_len(
FSP_HEADER_OFFSET + FSP_FREE+ header->page.frame);
/* Last file new size after truncation */
uint32_t new_last_file_size=
last_used_extent -
(fixed_size - srv_tmp_space.m_files.at(
srv_tmp_space.m_files.size() - 1).param_size());
space->size_in_header= space->size;
space->chain.end->size= new_last_file_size;
srv_tmp_space.set_last_file_size(new_last_file_size);
mysql_mutex_unlock(&fil_system.mutex);
os_file_truncate(
space->chain.end->name, space->chain.end->handle,
os_offset_t{space->chain.end->size} << srv_page_size_shift, true);
mtr.commit();
sql_print_information("InnoDB: Temporary tablespace truncated successfully");
}
......@@ -47,6 +47,14 @@ void flst_write_addr(const buf_block_t &block, byte *faddr,
static_assert(FIL_ADDR_BYTE == 4, "compatibility");
static_assert(FIL_ADDR_SIZE == 6, "compatibility");
if (!mtr->is_logged())
{
mach_write_to_4(faddr + FIL_ADDR_PAGE, page);
mach_write_to_2(faddr + FIL_ADDR_BYTE, boffset);
mtr->set_modified(block);
return;
}
const bool same_page= mach_read_from_4(faddr + FIL_ADDR_PAGE) == page;
const bool same_offset= mach_read_from_2(faddr + FIL_ADDR_BYTE) == boffset;
if (same_page)
......
......@@ -213,6 +213,8 @@ enum default_row_format_enum {
DEFAULT_ROW_FORMAT_DYNAMIC = 2,
};
static my_bool innodb_truncate_temporary_tablespace_now;
/** Whether ROW_FORMAT=COMPRESSED tables are read-only */
static my_bool innodb_read_only_compressed;
......@@ -18492,6 +18494,20 @@ innodb_encrypt_tables_update(THD*, st_mysql_sys_var*, void*, const void* save)
mysql_mutex_lock(&LOCK_global_system_variables);
}
/** Truncate the temporary tablespace if the
innodb_truncate_temporary_tablespace_now is enabled.
@param save to-be-assigned value */
static
void
innodb_trunc_temp_space_update(THD*, st_mysql_sys_var*, void*, const void* save)
{
if (!*static_cast<const my_bool*>(save))
return;
mysql_mutex_unlock(&LOCK_global_system_variables);
fsp_shrink_temp_space();
mysql_mutex_lock(&LOCK_global_system_variables);
}
static SHOW_VAR innodb_status_variables_export[]= {
SHOW_FUNC_ENTRY("Innodb", &show_innodb_vars),
{NullS, NullS, SHOW_LONG}
......@@ -19583,6 +19599,12 @@ static MYSQL_SYSVAR_BOOL(encrypt_temporary_tables, innodb_encrypt_temporary_tabl
"Enrypt the temporary table data.",
NULL, NULL, false);
static MYSQL_SYSVAR_BOOL(truncate_temporary_tablespace_now,
innodb_truncate_temporary_tablespace_now,
PLUGIN_VAR_OPCMDARG,
"Shrink the temporary tablespace",
NULL, innodb_trunc_temp_space_update, false);
static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(autoextend_increment),
MYSQL_SYSVAR(buffer_pool_size),
......@@ -19741,6 +19763,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(buf_dump_status_frequency),
MYSQL_SYSVAR(background_thread),
MYSQL_SYSVAR(encrypt_temporary_tables),
MYSQL_SYSVAR(truncate_temporary_tablespace_now),
NULL
};
......
......@@ -129,6 +129,10 @@ buf_unzip_LRU_add_block(
ibool old); /*!< in: TRUE if should be put to the end
of the list, else put to the start */
/** Evict the temporary tablespace pages above the given threshold
@param threshold Above this page to be removed from LRU list */
void buf_LRU_truncate_temp(uint32_t threshold);
/** Update buf_pool.LRU_old_ratio.
@param[in] old_pct Reserve this percentage of
the buffer pool for "old" blocks
......
......@@ -911,6 +911,11 @@ struct fil_space_t final
freed_ranges.add_range(range);
}
/** Clear the freed range in temporary tablespace
which are in shrinking ranges.
@param threshold to be truncated value*/
inline void clear_freed_ranges(uint32_t threshold);
/** Set the tablespace size in pages */
void set_sizes(uint32_t s)
{
......
......@@ -576,6 +576,9 @@ inline void fsp_init_file_page(
/** Truncate the system tablespace */
void fsp_system_tablespace_truncate();
/** Truncate the temporary tablespace */
void fsp_shrink_temp_space();
#ifndef UNIV_DEBUG
# define fsp_init_file_page(space, block, mtr) fsp_init_file_page(block, mtr)
#endif
......
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