|
Waiting for purge before the DROP TABLE dramatically improves reproducibility:
diff --git a/mysql-test/suite/innodb_zip/r/page_size.result b/mysql-test/suite/innodb_zip/r/page_size.result
|
index e65a57326ec..c823c9d0d3f 100644
|
--- a/mysql-test/suite/innodb_zip/r/page_size.result
|
+++ b/mysql-test/suite/innodb_zip/r/page_size.result
|
@@ -566,6 +566,7 @@ SET @r = repeat('e', 48);
|
INSERT INTO t1 VALUES(@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,
|
@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
|
DELETE from t1;
|
+InnoDB 0 transactions not purged
|
DROP TABLE t1;
|
CREATE TABLE t1(
|
c text NOT NULL, d text NOT NULL,
|
diff --git a/mysql-test/suite/innodb_zip/t/page_size.test b/mysql-test/suite/innodb_zip/t/page_size.test
|
index 0faf4428f62..c8d2a3c4d2a 100644
|
--- a/mysql-test/suite/innodb_zip/t/page_size.test
|
+++ b/mysql-test/suite/innodb_zip/t/page_size.test
|
@@ -3,6 +3,8 @@
|
SET default_storage_engine=InnoDB;
|
|
--disable_query_log
|
+SET @save_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
|
+SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
|
let $MYSQLD_DATADIR = `select @@datadir`;
|
let $INNODB_PAGE_SIZE = `select @@innodb_page_size`;
|
|
@@ -821,6 +823,7 @@ SET @r = repeat('e', 48);
|
INSERT INTO t1 VALUES(@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,
|
@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
|
DELETE from t1;
|
+--source ../../innodb/include/wait_all_purged.inc
|
DROP TABLE t1;
|
|
#-- disable_query_log
|
@@ -872,3 +875,6 @@ CREATE TABLE t1(c text, PRIMARY KEY (c(438)))
|
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512));
|
DROP TABLE t1;
|
+--disable_query_log
|
+SET GLOBAL innodb_purge_rseg_truncate_frequency=@save_frequency;
|
+--enable_query_log
|
It will still not fail every time. For a crash that I reproduced, node_ptr-block->frame in btr_discard_page() was 8351, which is more than the configured innodb_page_size=4k.
It requires a high concurrency to fail. I was also able to reproduce it for the 4k,full_crc32 combination.
|
|
There were two bugs in the code. The second one is an assertion that would fail if we had passed the correct parameter to the function call:
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
|
--- a/storage/innobase/btr/btr0btr.cc
|
+++ b/storage/innobase/btr/btr0btr.cc
|
@@ -4182,7 +4178,7 @@ btr_discard_page(
|
because everything will take place within a single
|
mini-transaction and because writing to the redo log
|
is an atomic operation (performed by mtr_commit()). */
|
- btr_set_min_rec_mark(node_ptr, *block, mtr);
|
+ btr_set_min_rec_mark(node_ptr, *merge_block, mtr);
|
}
|
|
if (dict_index_is_spatial(index)) {
|
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
|
--- a/storage/innobase/include/btr0btr.h
|
+++ b/storage/innobase/include/btr0btr.h
|
@@ -532,7 +532,6 @@ inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block,
|
{
|
ut_ad(block.frame == page_align(rec));
|
ut_ad(!page_is_leaf(block.frame));
|
- ut_ad(!page_has_prev(block.frame));
|
|
rec-= page_rec_is_comp(rec) ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS;
|
|
The assertion would fail, because only a subsequent call to btr_level_list_remove() in the same mini-transaction would make merge_block the leftmost on its level. I think that we can retain the assertion by refactoring the code a little more.
|