diff --git a/mysql-test/suite/maria/r/maria-recovery3.result b/mysql-test/suite/maria/r/maria-recovery3.result index 8c0661cba16..670104b2ba4 100644 --- a/mysql-test/suite/maria/r/maria-recovery3.result +++ b/mysql-test/suite/maria/r/maria-recovery3.result @@ -63,5 +63,31 @@ ok * compared t1 to old version use mysqltest; drop table t1; +create table t1 engine=maria select 1; +* copied t1 for feeding_recovery +set global maria_checkpoint_interval=0; +insert into t1 values(2); +truncate table t1; +flush table t1; +* copied t1 for comparison +truncate table t1; +SET SESSION debug="+d,maria_flush_whole_log,maria_crash_create_table"; +* crashing mysqld intentionally +truncate table t1; +ERROR HY000: Lost connection to MySQL server during query +* recovery happens +check table t1 extended; +Table Op Msg_type Msg_text +mysqltest.t1 check warning Size of indexfile is: 372 Should be: 8192 +mysqltest.t1 check status OK +* testing that checksum after recovery is as expected +Checksum-check +ok +use mysqltest; +truncate table t1; +check table t1 extended; +Table Op Msg_type Msg_text +mysqltest.t1 check status OK +drop table t1; drop database mysqltest_for_comparison; drop database mysqltest; diff --git a/mysql-test/suite/maria/t/maria-recovery3.test b/mysql-test/suite/maria/t/maria-recovery3.test index baee7978f2b..fc1883b1aa7 100644 --- a/mysql-test/suite/maria/t/maria-recovery3.test +++ b/mysql-test/suite/maria/t/maria-recovery3.test @@ -88,6 +88,28 @@ check table t1 extended; -- source include/maria_verify_recovery.inc drop table t1; +# Test for BUG#42112 "Maria: recovery failure (pushbuild2) Assertion +# `rownr == 0 && new_page' failed" + +let $mvr_restore_old_snapshot=0; +let $mms_compare_physically=0; +create table t1 engine=maria select 1; +-- source include/maria_make_snapshot_for_feeding_recovery.inc +set global maria_checkpoint_interval=0; # no checkpoints +insert into t1 values(2); +truncate table t1; +-- source include/maria_make_snapshot_for_comparison.inc +let $mvr_crash_statement= truncate table t1; +let $mvr_debug_option="+d,maria_flush_whole_log,maria_crash_create_table"; +truncate table t1; +-- source include/maria_verify_recovery.inc +# Table is bad but at least Recovery didn't crash and a new truncate +# can succeed: +truncate table t1; +check table t1 extended; +drop table t1; + + # clean up everything let $mms_purpose=comparison; eval drop database mysqltest_for_$mms_purpose; diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index f9ea1dab67e..903ef6bca9e 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -751,6 +751,13 @@ int maria_create(const char *name, enum data_file_type datafile_type, (via maria_recreate_table()) and it does not have a log. */ sync_dir= MY_SYNC_DIR; + /* + If crash between _ma_state_info_write_sub() and + _ma_update_state__lsns_sub(), table should be ignored by Recovery (or + old REDOs would fail), so we cannot let LSNs be 0: + */ + share.state.skip_redo_lsn= share.state.is_of_horizon= + share.state.create_rename_lsn= LSN_MAX; } if (datafile_type == DYNAMIC_RECORD) @@ -1060,11 +1067,21 @@ int maria_create(const char *name, enum data_file_type datafile_type, log_array, NULL, NULL) || translog_flush(lsn))) goto err; + share.kfile.file= file; + DBUG_EXECUTE_IF("maria_flush_whole_log", + { + DBUG_PRINT("maria_flush_whole_log", ("now")); + translog_flush(translog_get_horizon()); + }); + DBUG_EXECUTE_IF("maria_crash_create_table", + { + DBUG_PRINT("maria_crash_create_table", ("now")); + DBUG_ABORT(); + }); /* store LSN into file, needed for Recovery to not be confused if a DROP+CREATE happened (applying REDOs to the wrong table). */ - share.kfile.file= file; if (_ma_update_state_lsns_sub(&share, lsn, trnman_get_min_safe_trid(), FALSE, TRUE)) goto err; diff --git a/storage/maria/ma_delete_all.c b/storage/maria/ma_delete_all.c index b1e7596e4b9..bca4ef96554 100644 --- a/storage/maria/ma_delete_all.c +++ b/storage/maria/ma_delete_all.c @@ -115,6 +115,12 @@ int maria_delete_all_rows(MARIA_HA *info) but redo_insert are skipped (dirty pages list is empty). To avoid this, we need to set skip_redo_lsn now, and thus need to sync files. + Also fixes the problem of: + bulk insert; insert; delete_all; crash: + "bulk insert" is skipped (no REDOs), so if "insert" would not be skipped + (if we didn't update skip_redo_lsn below) then "insert" would be tried + and fail, saying that it sees that the first page has to be created + though the inserted row has rownr>0. */ my_bool error= _ma_state_info_write(share, 1|4) || _ma_update_state_lsns(share, lsn, trnman_get_min_trid(), FALSE, FALSE) ||