From d3b2625ba0c84e97ce508088b41cc33201929aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 9 Dec 2019 21:11:08 +0200 Subject: [PATCH] MDEV-21259 Assertion failed in mtr_t::write() btr_free_externally_stored_field(): Pass w=mtr_t::OPT to note that the BTR_EXTERN_LEN is not necessarily changing when a multi-page ROW_FORMAT=COMPRESSED off-page column is being freed, and to allow redundant writes to the redo log to be optimized away. Ever since commit 56f6dab1d0e5a464ea49c1e5efb0032a0f5cea3e the refactored function mtr_t::write() asserts by default that the page contents is being changed. --- mysql-test/suite/innodb_zip/r/blob.result | 21 ++++++++++++++++ mysql-test/suite/innodb_zip/t/blob.test | 29 +++++++++++++++++++++++ storage/innobase/btr/btr0cur.cc | 6 ++--- 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 mysql-test/suite/innodb_zip/r/blob.result create mode 100644 mysql-test/suite/innodb_zip/t/blob.test diff --git a/mysql-test/suite/innodb_zip/r/blob.result b/mysql-test/suite/innodb_zip/r/blob.result new file mode 100644 index 00000000000..bfe96b8a869 --- /dev/null +++ b/mysql-test/suite/innodb_zip/r/blob.result @@ -0,0 +1,21 @@ +# +# MDEV-21259 Assertion 'w != NORMAL || mach_read_from_4(ptr) != val' +# failed in mtr_t::write(), btr_free_externally_stored_field() +# +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; +CREATE TABLE t1 (c TEXT, f2 INT PRIMARY KEY, f3 INT UNIQUE) +ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; +SET @level= @@GLOBAL.innodb_compression_level; +SET GLOBAL innodb_compression_level=0; +connect prevent_purge,localhost,root; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +connection default; +INSERT INTO t1 VALUES('a',1,0); +UPDATE t1 SET c= REPEAT('a b ',4096); +REPLACE INTO t1 SELECT * FROM t1; +disconnect prevent_purge; +InnoDB 0 transactions not purged +DROP TABLE t1; +SET GLOBAL innodb_compression_level = @level; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb_zip/t/blob.test b/mysql-test/suite/innodb_zip/t/blob.test new file mode 100644 index 00000000000..b85cf7313d0 --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/blob.test @@ -0,0 +1,29 @@ +--source include/innodb_page_size_small.inc + +--echo # +--echo # MDEV-21259 Assertion 'w != NORMAL || mach_read_from_4(ptr) != val' +--echo # failed in mtr_t::write(), btr_free_externally_stored_field() +--echo # + +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; + +CREATE TABLE t1 (c TEXT, f2 INT PRIMARY KEY, f3 INT UNIQUE) +ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; + +SET @level= @@GLOBAL.innodb_compression_level; +SET GLOBAL innodb_compression_level=0; +--connect (prevent_purge,localhost,root) +START TRANSACTION WITH CONSISTENT SNAPSHOT; + +--connection default +INSERT INTO t1 VALUES('a',1,0); +UPDATE t1 SET c= REPEAT('a b ',4096); +REPLACE INTO t1 SELECT * FROM t1; + +--disconnect prevent_purge +--source ../../innodb/include/wait_all_purged.inc + +DROP TABLE t1; +SET GLOBAL innodb_compression_level = @level; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 932072ad182..cf3d0839e86 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -8110,9 +8110,9 @@ btr_free_externally_stored_field( mtr.write<4>(*block, BTR_EXTERN_PAGE_NO + field_ref, next_page_no); - mtr.write<4>(*block, - BTR_EXTERN_LEN + 4 + field_ref, - 0U); + mtr.write<4,mtr_t::OPT>(*block, + BTR_EXTERN_LEN + 4 + + field_ref, 0U); } } else { ut_ad(!block->page.zip.data);