diff --git a/mysql-test/suite/innodb/r/percona_bug_ps9297.result b/mysql-test/suite/innodb/r/percona_bug_ps9297.result new file mode 100644 index 000000000000..50f93892dbe0 --- /dev/null +++ b/mysql-test/suite/innodb/r/percona_bug_ps9297.result @@ -0,0 +1,42 @@ +create table c(id int primary key, val varchar(8000)); +insert into c values (1,repeat('a',3000)); +insert into c values (2,repeat('a',3000)); +insert into c values (3,repeat('a',3000)); +insert into c values (4,repeat('a',3000)); +insert into c values (5,repeat('a',3000)); +insert into c values (-1,repeat('a',2000)); +insert into c values (-2,repeat('a',2000)); +insert into c values (-3,repeat('a',2000)); +insert into c values (-4,repeat('a',2000)); +insert into c values (-5,repeat('a',2000)); +select id,length(val) from c order by id desc; +id length(val) +5 3000 +4 3000 +3 3000 +2 3000 +1 3000 +-1 2000 +-2 2000 +-3 2000 +-4 2000 +-5 2000 +set DEBUG="+d,desc_scan_debug"; +set DEBUG_SYNC="desc_scan_before_restore_position SIGNAL desc_scan_before_restore_position_done WAIT_FOR continue"; +select id,length(val) from c order by id desc; +set DEBUG_SYNC="now WAIT_FOR desc_scan_before_restore_position_done"; +update c set val=repeat('b',6000) where id=2; +set DEBUG_SYNC="now SIGNAL continue"; +id length(val) +5 3000 +4 3000 +3 3000 +2 3000 +1 3000 +-1 2000 +-2 2000 +-3 2000 +-4 2000 +-5 2000 +set DEBUG="-d,desc_scan_debug"; +drop table c; diff --git a/mysql-test/suite/innodb/t/percona_bug_ps9297.test b/mysql-test/suite/innodb/t/percona_bug_ps9297.test new file mode 100644 index 000000000000..1d16ca31c315 --- /dev/null +++ b/mysql-test/suite/innodb/t/percona_bug_ps9297.test @@ -0,0 +1,31 @@ +--source include/have_debug.inc + +connect (con1, localhost, root,,); +--connection default +create table c(id int primary key, val varchar(8000)); +insert into c values (1,repeat('a',3000)); +insert into c values (2,repeat('a',3000)); +insert into c values (3,repeat('a',3000)); +insert into c values (4,repeat('a',3000)); +insert into c values (5,repeat('a',3000)); + +insert into c values (-1,repeat('a',2000)); +insert into c values (-2,repeat('a',2000)); +insert into c values (-3,repeat('a',2000)); +insert into c values (-4,repeat('a',2000)); +insert into c values (-5,repeat('a',2000)); + +--connection con1 +select id,length(val) from c order by id desc; +set DEBUG="+d,desc_scan_debug"; +set DEBUG_SYNC="desc_scan_before_restore_position SIGNAL desc_scan_before_restore_position_done WAIT_FOR continue"; +send select id,length(val) from c order by id desc; +--connection default +set DEBUG_SYNC="now WAIT_FOR desc_scan_before_restore_position_done"; +update c set val=repeat('b',6000) where id=2; +set DEBUG_SYNC="now SIGNAL continue"; +--connection con1 +reap; +set DEBUG="-d,desc_scan_debug"; +--connection default +drop table c; \ No newline at end of file diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 1a37d11340c1..3ac0b147c21d 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -2313,6 +2313,11 @@ static rec_t *btr_insert_into_right_sibling(uint32_t flags, btr_cur_t *cursor, } } + /** We moved the record from the current page to the next page. Therefore, we + * need to disable optimistic access to the next page to ensure that the + * record will not be mistakenly skipped during reverse scanning on cursor. */ + buf_block_modify_clock_inc(next_block); + return (rec); } diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 67f431dc8d1d..5d4f509bee5e 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -419,6 +419,12 @@ void btr_pcur_t::move_backward_from_page(mtr_t *mtr) { mtr_commit(mtr); + DBUG_EXECUTE_IF("desc_scan_debug", { + if (strcmp(index()->table_name, "test/c") == 0) { + DEBUG_SYNC_C("desc_scan_before_restore_position"); + } + }); + mtr_start(mtr); restore_position(latch_mode2, mtr, UT_LOCATION_HERE);