Skip to content

Commit c507678

Browse files
Thirunarayanandr-m
authored andcommitted
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
1 parent 7b842f1 commit c507678

File tree

14 files changed

+371
-24
lines changed

14 files changed

+371
-24
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# restart
2+
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
3+
f2 INT NOT NULL)ENGINE=InnoDB;
4+
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
5+
DROP TABLE t1;
6+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
7+
NAME FILE_SIZE
8+
innodb_temporary 72351744
9+
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 0;
10+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
11+
NAME FILE_SIZE
12+
innodb_temporary 72351744
13+
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
14+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
15+
NAME FILE_SIZE
16+
innodb_temporary 5242880
17+
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
18+
f2 INT NOT NULL)ENGINE=InnoDB;
19+
BEGIN;
20+
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
21+
connect con1,localhost,root,,,;
22+
CREATE TEMPORARY TABLE t2(f1 INT NOT NULL,
23+
f2 INT NOT NULL)ENGINE=InnoDB;
24+
INSERT INTO t2 SELECT seq, seq FROM seq_1_to_65536;
25+
DROP TABLE t2;
26+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
27+
NAME FILE_SIZE
28+
innodb_temporary 72351744
29+
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
30+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
31+
NAME FILE_SIZE
32+
innodb_temporary 7340032
33+
connection default;
34+
COMMIT;
35+
SELECT COUNT(*) FROM t1;
36+
COUNT(*)
37+
65536
38+
DROP TABLE t1;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
call mtr.add_suppression("InnoDB: Cannot shrink the temporary tablespace");
2+
# restart
3+
SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=2;
4+
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
5+
f2 INT NOT NULL)ENGINE=InnoDB;
6+
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
7+
DROP TABLE t1;
8+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
9+
NAME FILE_SIZE
10+
innodb_temporary 1146093568
11+
SET @saved_debug_dbug = @@SESSION.debug_dbug;
12+
SET DEBUG_DBUG="+d,fail_temp_truncate";
13+
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
14+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
15+
NAME FILE_SIZE
16+
innodb_temporary 1146093568
17+
SET DEBUG_DBUG=@saved_debug_dbug;
18+
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
19+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
20+
NAME FILE_SIZE
21+
innodb_temporary 5242880
22+
SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=default;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--innodb_temp_data_file_path=ibtmp1:5M:autoextend
2+
--innodb_sys_tablespaces
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--source include/have_innodb.inc
2+
--source include/have_sequence.inc
3+
4+
--source include/restart_mysqld.inc
5+
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
6+
f2 INT NOT NULL)ENGINE=InnoDB;
7+
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
8+
DROP TABLE t1;
9+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
10+
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 0;
11+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
12+
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
13+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
14+
15+
# Concurrent session has open transaction for temporary tables
16+
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
17+
f2 INT NOT NULL)ENGINE=InnoDB;
18+
BEGIN;
19+
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
20+
21+
# Concurrent session has open transaction for temporary tables
22+
connect(con1,localhost,root,,,);
23+
CREATE TEMPORARY TABLE t2(f1 INT NOT NULL,
24+
f2 INT NOT NULL)ENGINE=InnoDB;
25+
INSERT INTO t2 SELECT seq, seq FROM seq_1_to_65536;
26+
DROP TABLE t2;
27+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE=4294967294;
28+
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
29+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
30+
31+
connection default;
32+
COMMIT;
33+
SELECT COUNT(*) FROM t1;
34+
DROP TABLE t1;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--innodb_temp_data_file_path=ibtmp1:5M:autoextend
2+
--innodb_sys_tablespaces
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--source include/have_innodb.inc
2+
--source include/have_sequence.inc
3+
--source include/have_debug.inc
4+
5+
call mtr.add_suppression("InnoDB: Cannot shrink the temporary tablespace");
6+
--source include/restart_mysqld.inc
7+
SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=2;
8+
CREATE TEMPORARY TABLE t1(f1 INT NOT NULL,
9+
f2 INT NOT NULL)ENGINE=InnoDB;
10+
INSERT INTO t1 SELECT seq, seq FROM seq_1_to_65536;
11+
DROP TABLE t1;
12+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
13+
14+
SET @saved_debug_dbug = @@SESSION.debug_dbug;
15+
SET DEBUG_DBUG="+d,fail_temp_truncate";
16+
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
17+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
18+
SET DEBUG_DBUG=@saved_debug_dbug;
19+
20+
SET GLOBAL INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW= 1;
21+
SELECT NAME, FILE_SIZE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE SPACE= 4294967294;
22+
SET GLOBAL INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG=default;

mysql-test/suite/sys_vars/r/sysvars_innodb.result

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,18 @@ NUMERIC_BLOCK_SIZE NULL
15311531
ENUM_VALUE_LIST NULL
15321532
READ_ONLY NO
15331533
COMMAND_LINE_ARGUMENT OPTIONAL
1534+
VARIABLE_NAME INNODB_TRUNCATE_TEMPORARY_TABLESPACE_NOW
1535+
SESSION_VALUE NULL
1536+
DEFAULT_VALUE OFF
1537+
VARIABLE_SCOPE GLOBAL
1538+
VARIABLE_TYPE BOOLEAN
1539+
VARIABLE_COMMENT Shrink the temporary tablespace
1540+
NUMERIC_MIN_VALUE NULL
1541+
NUMERIC_MAX_VALUE NULL
1542+
NUMERIC_BLOCK_SIZE NULL
1543+
ENUM_VALUE_LIST OFF,ON
1544+
READ_ONLY NO
1545+
COMMAND_LINE_ARGUMENT OPTIONAL
15341546
VARIABLE_NAME INNODB_TRX_PURGE_VIEW_UPDATE_ONLY_DEBUG
15351547
SESSION_VALUE NULL
15361548
DEFAULT_VALUE OFF

storage/innobase/buf/buf0lru.cc

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,51 @@ bool buf_LRU_scan_and_free_block(ulint limit)
13301330
buf_LRU_free_from_common_LRU_list(limit);
13311331
}
13321332

1333+
void buf_LRU_truncate_temp(uint32_t threshold)
1334+
{
1335+
/* Set the extent descriptor page state as FREED */
1336+
for (uint32_t cur_xdes_page= xdes_calc_descriptor_page(
1337+
0, fil_system.temp_space->free_limit);
1338+
cur_xdes_page >= threshold;)
1339+
{
1340+
mtr_t mtr;
1341+
mtr.start();
1342+
if (buf_block_t* block= buf_page_get_gen(
1343+
page_id_t(SRV_TMP_SPACE_ID, cur_xdes_page), 0, RW_X_LATCH,
1344+
nullptr, BUF_PEEK_IF_IN_POOL, &mtr))
1345+
{
1346+
uint32_t state= block->page.state();
1347+
ut_ad(state > buf_page_t::UNFIXED);
1348+
ut_ad(state < buf_page_t::READ_FIX);
1349+
block->page.set_freed(state);
1350+
}
1351+
cur_xdes_page-= uint32_t(srv_page_size);
1352+
mtr.commit();
1353+
}
1354+
1355+
const page_id_t limit{SRV_TMP_SPACE_ID, threshold};
1356+
mysql_mutex_lock(&buf_pool.mutex);
1357+
for (buf_page_t* bpage = UT_LIST_GET_FIRST(buf_pool.LRU);
1358+
bpage;)
1359+
{
1360+
buf_page_t* next= UT_LIST_GET_NEXT(LRU, bpage);
1361+
if (bpage->id() >= limit)
1362+
{
1363+
#ifdef UNIV_DEBUG
1364+
if (bpage->lock.u_lock_try(0))
1365+
{
1366+
ut_ad(bpage->state() == buf_page_t::FREED);
1367+
bpage->lock.u_unlock();
1368+
}
1369+
#endif /* UNIV_DEBUG */
1370+
ut_ad(!reinterpret_cast<buf_block_t*>(bpage)->index);
1371+
buf_LRU_free_page(bpage, true);
1372+
}
1373+
bpage= next;
1374+
}
1375+
mysql_mutex_unlock(&buf_pool.mutex);
1376+
}
1377+
13331378
#ifdef UNIV_DEBUG
13341379
/** Validate the LRU list. */
13351380
void buf_LRU_validate()

0 commit comments

Comments
 (0)