mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
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
This commit is contained in:
committed by
Marko Mäkelä
parent
7b842f1536
commit
c507678b20
38
mysql-test/suite/innodb/r/temp_truncate.result
Normal file
38
mysql-test/suite/innodb/r/temp_truncate.result
Normal file
@@ -0,0 +1,38 @@
|
||||
# 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;
|
22
mysql-test/suite/innodb/r/temp_truncate_debug.result
Normal file
22
mysql-test/suite/innodb/r/temp_truncate_debug.result
Normal file
@@ -0,0 +1,22 @@
|
||||
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;
|
2
mysql-test/suite/innodb/t/temp_truncate.opt
Normal file
2
mysql-test/suite/innodb/t/temp_truncate.opt
Normal file
@@ -0,0 +1,2 @@
|
||||
--innodb_temp_data_file_path=ibtmp1:5M:autoextend
|
||||
--innodb_sys_tablespaces
|
34
mysql-test/suite/innodb/t/temp_truncate.test
Normal file
34
mysql-test/suite/innodb/t/temp_truncate.test
Normal file
@@ -0,0 +1,34 @@
|
||||
--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;
|
2
mysql-test/suite/innodb/t/temp_truncate_debug.opt
Normal file
2
mysql-test/suite/innodb/t/temp_truncate_debug.opt
Normal file
@@ -0,0 +1,2 @@
|
||||
--innodb_temp_data_file_path=ibtmp1:5M:autoextend
|
||||
--innodb_sys_tablespaces
|
22
mysql-test/suite/innodb/t/temp_truncate_debug.test
Normal file
22
mysql-test/suite/innodb/t/temp_truncate_debug.test
Normal file
@@ -0,0 +1,22 @@
|
||||
--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 @@ public:
|
||||
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 @@ public:
|
||||
{
|
||||
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 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ func_exit:
|
||||
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 @@ func_exit:
|
||||
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 @@ func_exit:
|
||||
{
|
||||
/* 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 @@ func_exit:
|
||||
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 @@ func_exit:
|
||||
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 @@ mtr_max:
|
||||
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 @@ mtr_max:
|
||||
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 @@ public:
|
||||
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
|
||||
|
Reference in New Issue
Block a user