Skip to content

Commit 883333a

Browse files
dr-mvuvova
authored andcommitted
MDEV-31158: Potential hang with ROW_FORMAT=COMPRESSED tables
btr_cur_need_opposite_intention(): Check also page_zip_available() so that we will escalate to exclusive index latch when a non-leaf page may have to be split further due to ROW_FORMAT=COMPRESSED page overflow. Tested by: Matthias Leich
1 parent 459eb9a commit 883333a

File tree

3 files changed

+63
-9
lines changed

3 files changed

+63
-9
lines changed

mysql-test/suite/innodb_zip/r/page_size.result

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,4 +608,25 @@ SET GLOBAL innodb_compression_level=0;
608608
INSERT INTO t1 VALUES ('');
609609
SET GLOBAL innodb_compression_level= @save_innodb_compression_level;
610610
DROP TABLE t1;
611+
#
612+
# MDEV-31158 Assertion ...MTR_MEMO_X_LOCKED in btr_attach_half_pages()
613+
#
614+
SET @save_compression_level=@@GLOBAL.innodb_compression_level;
615+
SET GLOBAL innodb_compression_level=0;
616+
CREATE TEMPORARY TABLE t(a SERIAL, prefix VARBINARY(4), pad INT);
617+
INSERT INTO t(prefix, pad) VALUES
618+
(_binary 0xff,160),('',19),(_binary 0x0001,253),(_binary 0x0b11,169),
619+
(_binary 0x0b010001,23),(_binary 0x0b100001,251),(_binary 0x0d,163),
620+
(_binary 0xb3,254),(_binary 0x96,254),(_binary 0xeb,61),
621+
(_binary 0xf231,253),(_binary 0x1db0,253),(_binary 0x0005,101),
622+
(_binary 0x6370,253),(_binary 0x0b12,112),(_binary 0x0b010002,23),
623+
(_binary 0x0b100002,80),(_binary 0x181984,163),(_binary 0x181926,168),
624+
(_binary 0xe1,176),(_binary 0xe2,187),(_binary 0xe6,254),(_binary 0xbb,51),
625+
(_binary 0x1c,248),(_binary 0x8a,94),(_binary 0x14,254);
626+
CREATE TABLE u(a SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
627+
b VARBINARY(255), KEY(b)) ENGINE=InnoDB
628+
KEY_BLOCK_SIZE=1 ROW_FORMAT=COMPRESSED;
629+
INSERT INTO u SELECT a,CONCAT(prefix,REPEAT(chr(0),pad)) FROM t;
630+
DROP TABLE u, t;
631+
SET GLOBAL innodb_compression_level=@save_compression_level;
611632
# End of 10.6 tests

mysql-test/suite/innodb_zip/t/page_size.test

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,4 +888,28 @@ INSERT INTO t1 VALUES ('');
888888
SET GLOBAL innodb_compression_level= @save_innodb_compression_level;
889889
DROP TABLE t1;
890890

891+
--echo #
892+
--echo # MDEV-31158 Assertion ...MTR_MEMO_X_LOCKED in btr_attach_half_pages()
893+
--echo #
894+
--source include/have_innodb.inc
895+
896+
SET @save_compression_level=@@GLOBAL.innodb_compression_level;
897+
SET GLOBAL innodb_compression_level=0;
898+
CREATE TEMPORARY TABLE t(a SERIAL, prefix VARBINARY(4), pad INT);
899+
INSERT INTO t(prefix, pad) VALUES
900+
(_binary 0xff,160),('',19),(_binary 0x0001,253),(_binary 0x0b11,169),
901+
(_binary 0x0b010001,23),(_binary 0x0b100001,251),(_binary 0x0d,163),
902+
(_binary 0xb3,254),(_binary 0x96,254),(_binary 0xeb,61),
903+
(_binary 0xf231,253),(_binary 0x1db0,253),(_binary 0x0005,101),
904+
(_binary 0x6370,253),(_binary 0x0b12,112),(_binary 0x0b010002,23),
905+
(_binary 0x0b100002,80),(_binary 0x181984,163),(_binary 0x181926,168),
906+
(_binary 0xe1,176),(_binary 0xe2,187),(_binary 0xe6,254),(_binary 0xbb,51),
907+
(_binary 0x1c,248),(_binary 0x8a,94),(_binary 0x14,254);
908+
CREATE TABLE u(a SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
909+
b VARBINARY(255), KEY(b)) ENGINE=InnoDB
910+
KEY_BLOCK_SIZE=1 ROW_FORMAT=COMPRESSED;
911+
INSERT INTO u SELECT a,CONCAT(prefix,REPEAT(chr(0),pad)) FROM t;
912+
DROP TABLE u, t;
913+
SET GLOBAL innodb_compression_level=@save_compression_level;
914+
891915
--echo # End of 10.6 tests

storage/innobase/btr/btr0cur.cc

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -748,18 +748,24 @@ btr_cur_will_modify_tree(
748748

749749
/** Detects whether the modifying record might need a opposite modification
750750
to the intention.
751-
@param page page
752-
@param lock_intention lock intention for the tree operation
751+
@param bpage buffer pool page
752+
@param is_clust whether this is a clustered index
753+
@param lock_intention lock intention for the tree operation
753754
@param node_ptr_max_size the maximum size of a node pointer
754755
@param compress_limit BTR_CUR_PAGE_COMPRESS_LIMIT(index)
755-
@param rec record (current node_ptr)
756-
@return true if tree modification is needed */
757-
static bool btr_cur_need_opposite_intention(const page_t *page,
756+
@param rec record (current node_ptr)
757+
@return true if tree modification is needed */
758+
static bool btr_cur_need_opposite_intention(const buf_page_t &bpage,
759+
bool is_clust,
758760
btr_intention_t lock_intention,
759761
ulint node_ptr_max_size,
760762
ulint compress_limit,
761763
const rec_t *rec)
762764
{
765+
if (UNIV_LIKELY_NULL(bpage.zip.data) &&
766+
!page_zip_available(&bpage.zip, is_clust, node_ptr_max_size, 1))
767+
return true;
768+
const page_t *const page= bpage.frame;
763769
if (lock_intention != BTR_INTENTION_INSERT)
764770
{
765771
/* We compensate also for btr_cur_compress_recommendation() */
@@ -1342,7 +1348,8 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
13421348
!btr_block_get(*index(), btr_page_get_next(block->page.frame),
13431349
RW_X_LATCH, false, mtr, &err))
13441350
goto func_exit;
1345-
if (btr_cur_need_opposite_intention(block->page.frame, lock_intention,
1351+
if (btr_cur_need_opposite_intention(block->page, index()->is_clust(),
1352+
lock_intention,
13461353
node_ptr_max_size, compress_limit,
13471354
page_cur.rec))
13481355
goto need_opposite_intention;
@@ -1398,7 +1405,8 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
13981405
default:
13991406
break;
14001407
case BTR_MODIFY_TREE:
1401-
if (btr_cur_need_opposite_intention(block->page.frame, lock_intention,
1408+
if (btr_cur_need_opposite_intention(block->page, index()->is_clust(),
1409+
lock_intention,
14021410
node_ptr_max_size, compress_limit,
14031411
page_cur.rec))
14041412
/* If the rec is the first or last in the page for pessimistic
@@ -1948,7 +1956,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
19481956
break;
19491957

19501958
if (!index->lock.have_x() &&
1951-
btr_cur_need_opposite_intention(block->page.frame,
1959+
btr_cur_need_opposite_intention(block->page, index->is_clust(),
19521960
lock_intention,
19531961
node_ptr_max_size,
19541962
compress_limit, page_cur.rec))
@@ -1995,7 +2003,8 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
19952003
ut_ad(latch_mode != BTR_MODIFY_TREE || upper_rw_latch == RW_X_LATCH);
19962004

19972005
if (latch_mode != BTR_MODIFY_TREE);
1998-
else if (btr_cur_need_opposite_intention(block->page.frame, lock_intention,
2006+
else if (btr_cur_need_opposite_intention(block->page, index->is_clust(),
2007+
lock_intention,
19992008
node_ptr_max_size, compress_limit,
20002009
page_cur.rec))
20012010
{

0 commit comments

Comments
 (0)