MDEV-37192 Crash recovery reports corrupiton after bulk load

Problem:
=======
- InnoDB modifies the PAGE_ROOT_AUTO_INC value on clustered index
root page. But before committing the PAGE_ROOT_AUTO_INC changes
mini-transaction, InnoDB does bulk insert operation and
calculates the page checksum and store as a part of redo log in
mini-transaction. During recovery, InnoDB fails to validate the
page checksum.

Solution:
========
- Avoid writing the persistent auto increment value before doing
bulk insert operation.

- For bulk insert operation, persistent auto increment value
is written via btr_write_autoinc while applying the buffered
insert operation.
This commit is contained in:
Thirunarayanan Balathandayuthapani 2025-08-06 14:29:58 +05:30 committed by Thirunarayanan B
commit 05f9fd3dd2
3 changed files with 33 additions and 7 deletions

View file

@ -2,6 +2,7 @@ CREATE TABLE t1(f1 INT NOT NULL,f2 INT NOT NULL)ENGINE=InnoDB;
INSERT INTO t1 SELECT seq, seq from seq_1_to_131072; INSERT INTO t1 SELECT seq, seq from seq_1_to_131072;
INSERT INTO t1 VALUES(131073, 131073), (131074, 131073); INSERT INTO t1 VALUES(131073, 131073), (131074, 131073);
SELECT * INTO OUTFILE "VARDIR/tmp/t1.outfile" FROM t1; SELECT * INTO OUTFILE "VARDIR/tmp/t1.outfile" FROM t1;
SELECT * INTO OUTFILE "VARDIR/tmp/t.outfile" FROM t1 LIMIT 1;
# successful load statement using bulk insert # successful load statement using bulk insert
CREATE TABLE t2(f1 INT NOT NULL PRIMARY KEY, CREATE TABLE t2(f1 INT NOT NULL PRIMARY KEY,
f2 INT NOT NULL)ENGINE=InnoDB; f2 INT NOT NULL)ENGINE=InnoDB;
@ -48,3 +49,12 @@ CHECK TABLE t2 EXTENDED;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t2 check status OK test.t2 check status OK
DROP TABLE t2, t1; DROP TABLE t2, t1;
#
# MDEV-37192 Crash recovery reports corruption after bulk load
#
CREATE TABLE t2(f1 INT AUTO_INCREMENT, f2 INT NOT NULL,
PRIMARY KEY(f1))ENGINE=InnoDB;
BEGIN;
LOAD DATA INFILE 'VARDIR/tmp/t.outfile' INTO TABLE t2;
# restart
DROP TABLE t2;

View file

@ -1,6 +1,7 @@
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/have_sequence.inc --source include/have_sequence.inc
--source include/big_test.inc --source include/big_test.inc
--source include/not_embedded.inc
CREATE TABLE t1(f1 INT NOT NULL,f2 INT NOT NULL)ENGINE=InnoDB; CREATE TABLE t1(f1 INT NOT NULL,f2 INT NOT NULL)ENGINE=InnoDB;
INSERT INTO t1 SELECT seq, seq from seq_1_to_131072; INSERT INTO t1 SELECT seq, seq from seq_1_to_131072;
@ -9,6 +10,8 @@ INSERT INTO t1 VALUES(131073, 131073), (131074, 131073);
--disable_cursor_protocol --disable_cursor_protocol
--disable_ps2_protocol --disable_ps2_protocol
eval SELECT * INTO OUTFILE "$MYSQLTEST_VARDIR/tmp/t1.outfile" FROM t1; eval SELECT * INTO OUTFILE "$MYSQLTEST_VARDIR/tmp/t1.outfile" FROM t1;
--replace_result $MYSQLTEST_VARDIR VARDIR
eval SELECT * INTO OUTFILE "$MYSQLTEST_VARDIR/tmp/t.outfile" FROM t1 LIMIT 1;
--enable_ps2_protocol --enable_ps2_protocol
--enable_cursor_protocol --enable_cursor_protocol
@ -50,3 +53,16 @@ SELECT COUNT(*) FROM t2;
CHECK TABLE t2 EXTENDED; CHECK TABLE t2 EXTENDED;
--remove_file $MYSQLTEST_VARDIR/tmp/t1.outfile --remove_file $MYSQLTEST_VARDIR/tmp/t1.outfile
DROP TABLE t2, t1; DROP TABLE t2, t1;
--echo #
--echo # MDEV-37192 Crash recovery reports corruption after bulk load
--echo #
CREATE TABLE t2(f1 INT AUTO_INCREMENT, f2 INT NOT NULL,
PRIMARY KEY(f1))ENGINE=InnoDB;
BEGIN;
--replace_result $MYSQLTEST_VARDIR VARDIR
eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/t.outfile' INTO TABLE t2;
--let $shutdown_timeout=0
--source include/restart_mysqld.inc
--remove_file $MYSQLTEST_VARDIR/tmp/t.outfile
DROP TABLE t2;

View file

@ -2729,13 +2729,6 @@ err_exit:
goto func_exit; goto func_exit;
} }
if (auto_inc) {
buf_block_t* root
= mtr.at_savepoint(mode != BTR_MODIFY_ROOT_AND_LEAF);
ut_ad(index->page == root->page.id().page_no());
page_set_autoinc(root, auto_inc, &mtr, false);
}
btr_pcur_get_btr_cur(&pcur)->thr = thr; btr_pcur_get_btr_cur(&pcur)->thr = thr;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
@ -2854,6 +2847,13 @@ avoid_bulk:
} }
row_level_insert: row_level_insert:
if (auto_inc) {
buf_block_t* root =
mtr.at_savepoint(mode != BTR_MODIFY_ROOT_AND_LEAF);
ut_ad(index->page == root->page.id().page_no());
page_set_autoinc(root, auto_inc, &mtr, false);
}
if (UNIV_UNLIKELY(entry->info_bits != 0)) { if (UNIV_UNLIKELY(entry->info_bits != 0)) {
const rec_t* rec = btr_pcur_get_rec(&pcur); const rec_t* rec = btr_pcur_get_rec(&pcur);