diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2021-11-08 19:43:43 +0100 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2021-11-08 19:43:43 +0100 |
commit | 662fe08232d807f06da9665fa5a288717407f735 (patch) | |
tree | ef050eb11a648547c8f94dccc04862604d0f946c | |
parent | 8bd21167d28748bea8717183534db1103a696755 (diff) | |
parent | 30b0aa72d6160aef453bb743d85c256947706c98 (diff) | |
download | mariadb-git-662fe08232d807f06da9665fa5a288717407f735.tar.gz |
Merge branch '10.7' into bb-10.7-release
26 files changed, 199 insertions, 343 deletions
@@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=7 -MYSQL_VERSION_PATCH=1 +MYSQL_VERSION_PATCH=2 SERVER_MATURITY=gamma diff --git a/appveyor.yml b/appveyor.yml index 3c8a4364d59..6c14f321490 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,3 +1,9 @@ +init: + # Install bison + - choco feature disable --name showDownloadProgress + - choco install -y winflexbison + - C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe --version + version: build-{build}~branch-{branch} clone_depth: 1 @@ -17,7 +23,7 @@ build_script: - set BUILD_TYPE=MinSizeRel - set GENERATOR=-GNinja - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" - - cmake -E time cmake %GENERATOR% .. -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DMYSQL_MAINTAINER_MODE=ERR -DFAST_BUILD=1 -DBISON_EXECUTABLE=C:\cygwin64\bin\bison -DPLUGIN_PERFSCHEMA=NO -DPLUGIN_FEEDBACK=NO + - cmake -E time cmake %GENERATOR% .. -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DMYSQL_MAINTAINER_MODE=ERR -DFAST_BUILD=1 -DBISON_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe -DPLUGIN_PERFSCHEMA=NO -DPLUGIN_FEEDBACK=NO - set /A jobs=2*%NUMBER_OF_PROCESSORS% - cmake -E time cmake --build . -j %jobs% --config %BUILD_TYPE% --target minbuild diff --git a/mysql-test/suite/innodb/r/alter_kill.result b/mysql-test/suite/innodb/r/alter_kill.result index 5c2e154f6a2..0283d1079e1 100644 --- a/mysql-test/suite/innodb/r/alter_kill.result +++ b/mysql-test/suite/innodb/r/alter_kill.result @@ -11,7 +11,7 @@ InnoDB 0 transactions not purged connection default; # Cleanly shutdown mysqld disconnect con1; -# Corrupt FIL_PAGE_OFFSET in bug16720368.ibd, +# Corrupt FIL_PAGE_TYPE in bug16720368.ibd, # and recompute innodb_checksum_algorithm=crc32 # restart SELECT COUNT(*) FROM bug16720368; diff --git a/mysql-test/suite/innodb/r/insert_into_empty.result b/mysql-test/suite/innodb/r/insert_into_empty.result index b35b508fa7f..f33bef890fd 100644 --- a/mysql-test/suite/innodb/r/insert_into_empty.result +++ b/mysql-test/suite/innodb/r/insert_into_empty.result @@ -182,3 +182,43 @@ CREATE TABLE t (i INT) ENGINE=InnoDB PARTITION BY HASH (i) PARTITIONS 2; INSERT INTO t VALUES (0); INSERT INTO t VALUES (1),(0),(1); DROP TABLE t; +# +# MDEV-26947 UNIQUE column checks fail in InnoDB resulting +# in table corruption +# +CREATE TABLE t (c1 INT KEY,c2 INT UNIQUE) ENGINE=InnoDB; +BEGIN; +INSERT INTO t VALUES (1,0),(2,0); +ERROR HY000: Got error 1 "Operation not permitted" during COMMIT +CHECK TABLE t; +Table Op Msg_type Msg_text +test.t check status OK +COMMIT; +DROP TABLE t; +CREATE TABLE t (i INT UNIQUE)ENGINE=InnoDB; +INSERT INTO t VALUES (0),(0); +ERROR HY000: Got error 1 "Operation not permitted" during COMMIT +CHECK TABLE t; +Table Op Msg_type Msg_text +test.t check status OK +DROP TABLE t; +CREATE TABLE t (c INT PRIMARY KEY,c2 CHAR(1) UNIQUE)ENGINE=InnoDB; +BEGIN; +INSERT INTO t VALUES(1, ''),(2, ''); +ERROR HY000: Got error 1 "Operation not permitted" during COMMIT +SELECT * FROM t; +c c2 +DELETE FROM t; +COMMIT; +DROP TABLE t; +# +# MDEV-26956 LeakSanitizer/Valgrind errors in +# trx_mod_table_time_t::start_bulk_insert +# upon adding system versioning +# +CREATE TABLE t1(id INT, s DATE, e DATE, PERIOD FOR p(s,e), +PRIMARY KEY(id, p WITHOUT OVERLAPS)) ENGINE=InnoDB; +ALTER TABLE t1 ADD COLUMN row_start BIGINT UNSIGNED AS ROW START, +ADD COLUMN row_end BIGINT UNSIGNED AS ROW END, +ADD PERIOD FOR SYSTEM_TIME(row_start,row_end), WITH SYSTEM VERSIONING; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/alter_kill.test b/mysql-test/suite/innodb/t/alter_kill.test index a90fa9e6e3e..49aff22c89a 100644 --- a/mysql-test/suite/innodb/t/alter_kill.test +++ b/mysql-test/suite/innodb/t/alter_kill.test @@ -43,7 +43,7 @@ connection default; disconnect con1; --- echo # Corrupt FIL_PAGE_OFFSET in bug16720368.ibd, +-- echo # Corrupt FIL_PAGE_TYPE in bug16720368.ibd, -- echo # and recompute innodb_checksum_algorithm=crc32 perl; do "$ENV{MTR_SUITE_DIR}/include/crc32.pl"; @@ -56,7 +56,7 @@ die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps; my $full_crc32 = unpack("N",substr($page,54,4)) & 0x10; # FIL_SPACE_FLAGS sysseek(FILE, 3*$ps, 0) || die "Unable to seek $file\n"; die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps; -substr($page,4,4)=pack("N",0xc001cafe); +substr($page,24,2)='42'; my $polynomial = 0x82f63b78; # CRC-32C if ($full_crc32) { @@ -86,7 +86,7 @@ INSERT INTO bug16720368_1 VALUES(1); -- echo # Shut down the server to uncorrupt the data. -- source include/shutdown_mysqld.inc -# Uncorrupt the FIL_PAGE_OFFSET. +# Uncorrupt the FIL_PAGE_TYPE. perl; do "$ENV{MTR_SUITE_DIR}/include/crc32.pl"; my $file = "$ENV{MYSQLD_DATADIR}/test/bug16720368.ibd"; @@ -98,7 +98,7 @@ die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps; my $full_crc32 = unpack("N",substr($page,54,4)) & 0x10; # FIL_SPACE_FLAGS sysseek(FILE, 3*$ps, 0) || die "Unable to seek $file\n"; die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps; -substr($page,4,4)=pack("N",3); +substr($page,24,2)=pack("H*","45BF"); my $polynomial = 0x82f63b78; # CRC-32C if ($full_crc32) { diff --git a/mysql-test/suite/innodb/t/insert_into_empty.test b/mysql-test/suite/innodb/t/insert_into_empty.test index 8b885cb5b4f..7719ae68d7b 100644 --- a/mysql-test/suite/innodb/t/insert_into_empty.test +++ b/mysql-test/suite/innodb/t/insert_into_empty.test @@ -193,3 +193,43 @@ CREATE TABLE t (i INT) ENGINE=InnoDB PARTITION BY HASH (i) PARTITIONS 2; INSERT INTO t VALUES (0); INSERT INTO t VALUES (1),(0),(1); DROP TABLE t; + +--echo # +--echo # MDEV-26947 UNIQUE column checks fail in InnoDB resulting +--echo # in table corruption +--echo # + +CREATE TABLE t (c1 INT KEY,c2 INT UNIQUE) ENGINE=InnoDB; +BEGIN; +--error ER_ERROR_DURING_COMMIT +INSERT INTO t VALUES (1,0),(2,0); +CHECK TABLE t; +COMMIT; +DROP TABLE t; + +CREATE TABLE t (i INT UNIQUE)ENGINE=InnoDB; +--error ER_ERROR_DURING_COMMIT +INSERT INTO t VALUES (0),(0); +CHECK TABLE t; +DROP TABLE t; + +CREATE TABLE t (c INT PRIMARY KEY,c2 CHAR(1) UNIQUE)ENGINE=InnoDB; +BEGIN; +--error ER_ERROR_DURING_COMMIT +INSERT INTO t VALUES(1, ''),(2, ''); +SELECT * FROM t; +DELETE FROM t; +COMMIT; +DROP TABLE t; + +--echo # +--echo # MDEV-26956 LeakSanitizer/Valgrind errors in +--echo # trx_mod_table_time_t::start_bulk_insert +--echo # upon adding system versioning +--echo # +CREATE TABLE t1(id INT, s DATE, e DATE, PERIOD FOR p(s,e), + PRIMARY KEY(id, p WITHOUT OVERLAPS)) ENGINE=InnoDB; +ALTER TABLE t1 ADD COLUMN row_start BIGINT UNSIGNED AS ROW START, + ADD COLUMN row_end BIGINT UNSIGNED AS ROW END, + ADD PERIOD FOR SYSTEM_TIME(row_start,row_end), WITH SYSTEM VERSIONING; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/log_corruption.test b/mysql-test/suite/innodb/t/log_corruption.test index 01b3da3f7ac..b9162be99db 100644 --- a/mysql-test/suite/innodb/t/log_corruption.test +++ b/mysql-test/suite/innodb/t/log_corruption.test @@ -57,7 +57,14 @@ my $body = pack("x[8]Nx[10]Nx[16312]", 768, 97937874); my $ck = mycrc32($head, 0, $polynomial) ^ mycrc32($body, 0, $polynomial); print OUT pack("N",$ck).$head.pack("x[12]").$body.pack("Nx[4]",$ck); # Dummy pages 1..6. -print OUT chr(0) x (6 * 16384); +$body = pack("x[16338]"); +for (my($page) = 1; $page < 7; $page++) +{ + ## FIL_PAGE_OFFSET + $head = pack("Nx[18]", $page); + $ck = mycrc32($head, 0, $polynomial) ^ mycrc32($body, 0, $polynomial); + print OUT pack("N",$ck).$head.pack("x[16350]Nx[4]",$ck); +} # Dictionary header page (page 7). ## FIL_PAGE_OFFSET $head = pack("Nx[18]", 7); diff --git a/mysql-test/suite/innodb/t/page_id_innochecksum.test b/mysql-test/suite/innodb/t/page_id_innochecksum.test index 2726b3254da..f5166018dd1 100644 --- a/mysql-test/suite/innodb/t/page_id_innochecksum.test +++ b/mysql-test/suite/innodb/t/page_id_innochecksum.test @@ -61,5 +61,9 @@ let SEARCH_PATTERN=page id mismatch; --source include/search_pattern_in_file.inc --remove_file $resultlog +# prevent purge from crashing on page ID mismatch +let $restart_parameters=--innodb-force-recovery=2; --source include/start_mysqld.inc drop table t1; +let $restart_parameters=; +--source include/restart_mysqld.inc diff --git a/mysql-test/suite/sys_vars/r/innodb_force_load_corrupted_basic.result b/mysql-test/suite/sys_vars/r/innodb_force_load_corrupted_basic.result deleted file mode 100644 index bc9b7019eb8..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_force_load_corrupted_basic.result +++ /dev/null @@ -1,53 +0,0 @@ -'#---------------------BS_STVARS_031_01----------------------#' -SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted); -COUNT(@@GLOBAL.innodb_force_load_corrupted) -1 -1 Expected -'#---------------------BS_STVARS_031_02----------------------#' -SET @@GLOBAL.innodb_force_load_corrupted=1; -ERROR HY000: Variable 'innodb_force_load_corrupted' is a read only variable -Expected error 'Read only variable' -SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted); -COUNT(@@GLOBAL.innodb_force_load_corrupted) -1 -1 Expected -'#---------------------BS_STVARS_031_03----------------------#' -SELECT IF(@@GLOBAL.innodb_force_load_corrupted, "ON", "OFF") = VARIABLE_VALUE -FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES -WHERE VARIABLE_NAME='innodb_force_load_corrupted'; -IF(@@GLOBAL.innodb_force_load_corrupted, "ON", "OFF") = VARIABLE_VALUE -1 -1 Expected -SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted); -COUNT(@@GLOBAL.innodb_force_load_corrupted) -1 -1 Expected -SELECT COUNT(VARIABLE_VALUE) -FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES -WHERE VARIABLE_NAME='innodb_force_load_corrupted'; -COUNT(VARIABLE_VALUE) -1 -1 Expected -'#---------------------BS_STVARS_031_04----------------------#' -SELECT @@innodb_force_load_corrupted = @@GLOBAL.innodb_force_load_corrupted; -@@innodb_force_load_corrupted = @@GLOBAL.innodb_force_load_corrupted -1 -1 Expected -'#---------------------BS_STVARS_031_05----------------------#' -SELECT COUNT(@@innodb_force_load_corrupted); -COUNT(@@innodb_force_load_corrupted) -1 -1 Expected -SELECT COUNT(@@local.innodb_force_load_corrupted); -ERROR HY000: Variable 'innodb_force_load_corrupted' is a GLOBAL variable -Expected error 'Variable is a GLOBAL variable' -SELECT COUNT(@@SESSION.innodb_force_load_corrupted); -ERROR HY000: Variable 'innodb_force_load_corrupted' is a GLOBAL variable -Expected error 'Variable is a GLOBAL variable' -SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted); -COUNT(@@GLOBAL.innodb_force_load_corrupted) -1 -1 Expected -SELECT innodb_force_load_corrupted = @@SESSION.innodb_force_load_corrupted; -ERROR 42S22: Unknown column 'innodb_force_load_corrupted' in 'field list' -Expected error 'Readonly variable' diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 068ef4da079..a893bd007dd 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -765,18 +765,6 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT NONE -VARIABLE_NAME INNODB_FORCE_LOAD_CORRUPTED -SESSION_VALUE NULL -DEFAULT_VALUE OFF -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Force InnoDB to load metadata of corrupted table. -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON -READ_ONLY YES -COMMAND_LINE_ARGUMENT NONE VARIABLE_NAME INNODB_FORCE_PRIMARY_KEY SESSION_VALUE NULL DEFAULT_VALUE OFF diff --git a/mysql-test/suite/sys_vars/t/innodb_force_load_corrupted_basic.test b/mysql-test/suite/sys_vars/t/innodb_force_load_corrupted_basic.test deleted file mode 100644 index f12f2f670a4..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_force_load_corrupted_basic.test +++ /dev/null @@ -1,106 +0,0 @@ - - -################## mysql-test\t\innodb_force_load_corrupted_basic.test ##### -# # -# Variable Name: innodb_force_load_corrupted # -# Scope: Global # -# Access Type: Static # -# Data Type: boolean # -# # -# # -# Creation Date: 2008-02-07 # -# Author : Sharique Abdullah # -# # -# # -# Description:Test Cases of Dynamic System Variable innodb_force_load_corrupted# -# that checks the behavior of this variable in the following ways # -# * Value Check # -# * Scope Check # -# # -# Reference: http://dev.mysql.com/doc/refman/5.1/en/ # -# server-system-variables.html # -# # -############################################################################### - ---source include/have_innodb.inc - ---echo '#---------------------BS_STVARS_031_01----------------------#' -#################################################################### -# Displaying default value # -#################################################################### -SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted); ---echo 1 Expected - - ---echo '#---------------------BS_STVARS_031_02----------------------#' -#################################################################### -# Check if Value can set # -#################################################################### - ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -SET @@GLOBAL.innodb_force_load_corrupted=1; ---echo Expected error 'Read only variable' - -SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted); ---echo 1 Expected - - - - ---echo '#---------------------BS_STVARS_031_03----------------------#' -################################################################# -# Check if the value in GLOBAL Table matches value in variable # -################################################################# - ---disable_warnings -SELECT IF(@@GLOBAL.innodb_force_load_corrupted, "ON", "OFF") = VARIABLE_VALUE -FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES -WHERE VARIABLE_NAME='innodb_force_load_corrupted'; ---enable_warnings ---echo 1 Expected - -SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted); ---echo 1 Expected - ---disable_warnings -SELECT COUNT(VARIABLE_VALUE) -FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES -WHERE VARIABLE_NAME='innodb_force_load_corrupted'; ---enable_warnings ---echo 1 Expected - - - ---echo '#---------------------BS_STVARS_031_04----------------------#' -################################################################################ -# Check if accessing variable with and without GLOBAL point to same variable # -################################################################################ -SELECT @@innodb_force_load_corrupted = @@GLOBAL.innodb_force_load_corrupted; ---echo 1 Expected - - - ---echo '#---------------------BS_STVARS_031_05----------------------#' -################################################################################ -# Check if innodb_force_load_corrupted can be accessed with and without @@ sign # -################################################################################ - -SELECT COUNT(@@innodb_force_load_corrupted); ---echo 1 Expected - ---Error ER_INCORRECT_GLOBAL_LOCAL_VAR -SELECT COUNT(@@local.innodb_force_load_corrupted); ---echo Expected error 'Variable is a GLOBAL variable' - ---Error ER_INCORRECT_GLOBAL_LOCAL_VAR -SELECT COUNT(@@SESSION.innodb_force_load_corrupted); ---echo Expected error 'Variable is a GLOBAL variable' - -SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted); ---echo 1 Expected - ---Error ER_BAD_FIELD_ERROR -SELECT innodb_force_load_corrupted = @@SESSION.innodb_force_load_corrupted; ---echo Expected error 'Readonly variable' - - diff --git a/plugin/type_uuid/item_uuidfunc.h b/plugin/type_uuid/item_uuidfunc.h index add4f202784..296b6592f10 100644 --- a/plugin/type_uuid/item_uuidfunc.h +++ b/plugin/type_uuid/item_uuidfunc.h @@ -27,25 +27,25 @@ protected: { return MY_UUID_BARE_STRING_LENGTH + with_dashes*MY_UUID_SEPARATORS; } public: Item_func_sys_guid(THD *thd): Item_str_func(thd), with_dashes(false) {} - bool fix_length_and_dec() + bool fix_length_and_dec() override { collation.set(DTCollation_numeric()); fix_char_length(uuid_len()); return FALSE; } - bool const_item() const { return false; } - table_map used_tables() const { return RAND_TABLE_BIT; } + bool const_item() const override { return false; } + table_map used_tables() const override { return RAND_TABLE_BIT; } LEX_CSTRING func_name_cstring() const override { static LEX_CSTRING name= {STRING_WITH_LEN("sys_guid") }; return name; } String *val_str(String *) override; - bool check_vcol_func_processor(void *arg) + bool check_vcol_func_processor(void *arg) override { return mark_unsupported_function(func_name(), "()", arg, VCOL_NON_DETERMINISTIC); } - Item *get_copy(THD *thd) + Item *get_copy(THD *thd) override { return get_item_copy<Item_func_sys_guid>(thd, this); } }; @@ -60,7 +60,7 @@ public: return name; } bool val_native(THD *thd, Native *to) override; - Item *get_copy(THD *thd) + Item *get_copy(THD *thd) override { return get_item_copy<Item_func_uuid>(thd, this); } }; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4e5c61ec00b..df64bb5e27d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5142,6 +5142,9 @@ static int init_server_components() MYSQL_COMPATIBILITY_OPTION("new"), MYSQL_COMPATIBILITY_OPTION("show_compatibility_56"), + /* The following options were removed in 10.6 */ + MARIADB_REMOVED_OPTION("innodb-force-load-corrupted"), + /* The following options were removed in 10.5 */ #if defined(__linux__) MARIADB_REMOVED_OPTION("super-large-pages"), diff --git a/sql/sql_type_fixedbin.h b/sql/sql_type_fixedbin.h index b7dcfdde9d3..332b712db31 100644 --- a/sql/sql_type_fixedbin.h +++ b/sql/sql_type_fixedbin.h @@ -1428,7 +1428,7 @@ public: item->type_handler() == type_handler()); return true; } - void hash(ulong *nr, ulong *nr2) + void hash(ulong *nr, ulong *nr2) override { if (is_null()) *nr^= (*nr << 1) | 1; diff --git a/sql/table.cc b/sql/table.cc index df94cac6475..b183ebd3254 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -9711,6 +9711,9 @@ bool TR_table::update(ulonglong start_id, ulonglong end_id) int error= table->file->ha_write_row(table->record[0]); if (unlikely(error)) table->file->print_error(error, MYF(0)); + /* extra() is used to apply the bulk insert operation + on mysql/transaction_registry table */ + table->file->extra(HA_EXTRA_IGNORE_INSERT); return error; } diff --git a/sql/upgrade_conf_file.cc b/sql/upgrade_conf_file.cc index a30502d0dea..543df7b9bdf 100644 --- a/sql/upgrade_conf_file.cc +++ b/sql/upgrade_conf_file.cc @@ -80,6 +80,7 @@ static const char *removed_variables[] = "innodb_file_format_check", "innodb_file_format_max", "innodb_flush_neighbor_pages", +"innodb_force_load_corrupted", "innodb_foreground_preflush", "innodb_ibuf_accel_rate", "innodb_ibuf_active_contract", diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 2cccf976089..2ebb6d5c1e0 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -3260,7 +3260,7 @@ loop: free_block->page.set_state(BUF_BLOCK_FILE_PAGE); buf_unzip_LRU_add_block(free_block, FALSE); hash_lock.unlock(); - buf_page_free_descriptor(&block->page); + buf_page_free_descriptor(reinterpret_cast<buf_page_t*>(block)); block= free_block; buf_block_buf_fix_inc(block); mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX); diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index cf976d0680a..9723f50359b 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -654,7 +654,7 @@ dict_build_index_def_step( index = node->index; table = dict_table_open_on_name( - node->table_name, true, DICT_ERR_IGNORE_DROP); + node->table_name, true, DICT_ERR_IGNORE_TABLESPACE); if (!table) { return DB_TABLE_NOT_FOUND; diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 280a42d12c7..dddb22b93c2 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -145,10 +145,6 @@ dict_load_field_low( for temporary storage */ const rec_t* rec); /*!< in: SYS_FIELDS record */ -/* If this flag is TRUE, then we will load the cluster index's (and tables') -metadata even if it is marked as "corrupted". */ -my_bool srv_load_corrupted; - #ifdef UNIV_DEBUG /****************************************************************//** Compare the name of an index column. @@ -1831,31 +1827,11 @@ dict_load_indexes( btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); - for (;;) { + while (btr_pcur_is_on_user_rec(&pcur)) { dict_index_t* index = NULL; const char* err_msg; - if (!btr_pcur_is_on_user_rec(&pcur)) { - - /* We should allow the table to open even - without index when DICT_ERR_IGNORE_CORRUPT is set. - DICT_ERR_IGNORE_CORRUPT is currently only set - for drop table */ - if (dict_table_get_first_index(table) == NULL - && !(ignore_err & DICT_ERR_IGNORE_CORRUPT)) { - ib::warn() << "Cannot load table " - << table->name - << " because it has no indexes in" - " InnoDB internal data dictionary."; - error = DB_CORRUPTION; - goto func_exit; - } - - break; - } - rec = btr_pcur_get_rec(&pcur); - if ((ignore_err & DICT_ERR_IGNORE_RECOVER_LOCK) && (rec_get_n_fields_old(rec) == DICT_NUM_FIELDS__SYS_INDEXES @@ -1880,27 +1856,11 @@ dict_load_indexes( } err_msg = dict_load_index_low(buf, heap, rec, TRUE, &index); - ut_ad((index == NULL && err_msg != NULL) - || (index != NULL && err_msg == NULL)); + ut_ad(!index == !!err_msg); if (err_msg == dict_load_index_id_err) { - /* TABLE_ID mismatch means that we have - run out of index definitions for the table. */ - - if (dict_table_get_first_index(table) == NULL - && !(ignore_err & DICT_ERR_IGNORE_CORRUPT)) { - - ib::warn() << "Failed to load the" - " clustered index for table " - << table->name - << " because of TABLE_ID mismatch." - " Refusing to load the rest of the" - " indexes (if any) and the whole table" - " altogether."; - error = DB_CORRUPTION; - goto func_exit; - } - + /* We have ran out of index definitions for + the table. */ break; } @@ -1912,7 +1872,7 @@ dict_load_indexes( goto next_rec; } else if (err_msg) { ib::error() << err_msg; - if (ignore_err & DICT_ERR_IGNORE_CORRUPT) { + if (ignore_err & DICT_ERR_IGNORE_INDEX) { goto next_rec; } error = DB_CORRUPTION; @@ -1931,29 +1891,11 @@ dict_load_indexes( ut_ad(!dict_index_is_online_ddl(index)); /* Check whether the index is corrupted */ - if (index->is_corrupted()) { - ib::error() << "Index " << index->name - << " of table " << table->name - << " is corrupted"; - - if (!srv_load_corrupted - && !(ignore_err & DICT_ERR_IGNORE_CORRUPT) - && dict_index_is_clust(index)) { - dict_mem_index_free(index); - - error = DB_INDEX_CORRUPT; - goto func_exit; - } else { - /* We will load the index if - 1) srv_load_corrupted is TRUE - 2) ignore_err is set with - DICT_ERR_IGNORE_CORRUPT - 3) if the index corrupted is a secondary - index */ - ib::info() << "Load corrupted index " - << index->name - << " of table " << table->name; - } + if (ignore_err != DICT_ERR_IGNORE_DROP + && index->is_corrupted() && index->is_clust()) { + dict_mem_index_free(index); + error = DB_INDEX_CORRUPT; + goto func_exit; } if (index->type & DICT_FTS @@ -1979,31 +1921,30 @@ dict_load_indexes( } else if (index->page == FIL_NULL && table->is_readable() && (!(index->type & DICT_FTS))) { + if (ignore_err != DICT_ERR_IGNORE_DROP) { + ib::error_or_warn(!(ignore_err + & DICT_ERR_IGNORE_INDEX)) + << "Index " << index->name + << " for table " << table->name + << " has been freed!"; + } - ib::error() << "Trying to load index " << index->name - << " for table " << table->name - << ", but the index tree has been freed!"; - - if (ignore_err & DICT_ERR_IGNORE_INDEX_ROOT) { - /* If caller can tolerate this error, - we will continue to load the index and - let caller deal with this error. However - mark the index and table corrupted. We - only need to mark such in the index - dictionary cache for such metadata corruption, - since we would always be able to set it - when loading the dictionary cache */ - index->table = table; - dict_set_corrupted_index_cache_only(index); - - ib::info() << "Index is corrupt but forcing" - " load into data dictionary"; - } else { + if (!(ignore_err & DICT_ERR_IGNORE_INDEX)) { corrupted: dict_mem_index_free(index); error = DB_CORRUPTION; goto func_exit; } + /* If caller can tolerate this error, + we will continue to load the index and + let caller deal with this error. However + mark the index and table corrupted. We + only need to mark such in the index + dictionary cache for such metadata corruption, + since we would always be able to set it + when loading the dictionary cache */ + index->table = table; + dict_set_corrupted_index_cache_only(index); } else if (!dict_index_is_clust(index) && NULL == dict_table_get_first_index(table)) { @@ -2052,6 +1993,13 @@ next_rec: btr_pcur_move_to_next_user_rec(&pcur, &mtr); } + if (!dict_table_get_first_index(table) + && !(ignore_err & DICT_ERR_IGNORE_INDEX)) { + ib::warn() << "No indexes found for table " << table->name; + error = DB_CORRUPTION; + goto func_exit; + } + ut_ad(table->fts_doc_id_index == NULL); if (table->fts != NULL) { @@ -2219,7 +2167,7 @@ dict_load_tablespace( return; } - if (ignore_err == DICT_ERR_IGNORE_DROP) { + if (ignore_err >= DICT_ERR_IGNORE_TABLESPACE) { table->file_unreadable = true; return; } @@ -2382,32 +2330,31 @@ err_exit: if (err == DB_INDEX_CORRUPT) { /* Refuse to load the table if the table has a corrupted cluster index */ - if (!srv_load_corrupted) { - - ib::error() << "Load table " << table->name - << " failed, the table has" - " corrupted clustered indexes. Turn on" - " 'innodb_force_load_corrupted' to drop it"; - dict_sys.remove(table); - table = NULL; - goto func_exit; - } else { - if (table->indexes.start->is_corrupted()) { - table->corrupted = true; - } - } + ut_ad(index_load_err != DICT_ERR_IGNORE_DROP); + ib::error() << "Refusing to load corrupted table " + << table->name; +evict: + dict_sys.remove(table); + table = NULL; + goto func_exit; } - if (err == DB_SUCCESS && table->is_readable()) { - const auto root = dict_table_get_first_index(table)->page; - - if (root >= table->space->get_size()) { + if (err != DB_SUCCESS || !table->is_readable()) { + } else if (dict_index_t* pk = dict_table_get_first_index(table)) { + ut_ad(pk->is_primary()); + if (pk->is_corrupted() + || pk->page >= table->space->get_size()) { corrupted: table->corrupted = true; table->file_unreadable = true; err = DB_CORRUPTION; + } else if (table->space->id + && ignore_err == DICT_ERR_IGNORE_DROP) { + /* Do not bother to load data from .ibd files + only to delete the .ibd files. */ + goto corrupted; } else { - const page_id_t page_id(table->space->id, root); + const page_id_t page_id{table->space->id, pk->page}; mtr.start(); buf_block_t* block = buf_page_get( page_id, table->space->zip_size(), @@ -2432,6 +2379,12 @@ corrupted: err = btr_cur_instant_init(table); } } + } else { + ut_ad(ignore_err & DICT_ERR_IGNORE_INDEX); + if (ignore_err != DICT_ERR_IGNORE_DROP) { + err = DB_CORRUPTION; + goto evict; + } } /* Initialize table foreign_child value. Its value could be @@ -2454,33 +2407,11 @@ corrupted: << " failed, the table has missing" " foreign key indexes. Turn off" " 'foreign_key_checks' and try again."; -evict: - dict_sys.remove(table); - table = NULL; + goto evict; } else { dict_mem_table_fill_foreign_vcol_set(table); table->fk_max_recusive_level = 0; } - } else { - dict_index_t* index; - - /* Make sure that at least the clustered index was loaded. - Otherwise refuse to load the table */ - index = dict_table_get_first_index(table); - - if (!srv_force_recovery - || !index - || !index->is_primary()) { - ib::warn() << "Failed to load table " << table->name - << ":" << err; - goto evict; - } else if (index->is_corrupted() - && table->is_readable()) { - /* It is possible we force to load a corrupted - clustered index if srv_load_corrupted is set. - Mark the table as corrupted in this case */ - table->corrupted = true; - } } func_exit: diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 4949005e0d7..2a3a780228d 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1373,7 +1373,7 @@ fts_cache_add_doc( static dberr_t fts_drop_table(trx_t *trx, const char *table_name, bool rename) { if (dict_table_t *table= dict_table_open_on_name(table_name, true, - DICT_ERR_IGNORE_DROP)) + DICT_ERR_IGNORE_TABLESPACE)) { table->release(); if (rename) @@ -1505,7 +1505,7 @@ static dberr_t fts_lock_table(trx_t *trx, const char *table_name) ut_ad(purge_sys.must_wait_FTS()); if (dict_table_t *table= dict_table_open_on_name(table_name, false, - DICT_ERR_IGNORE_DROP)) + DICT_ERR_IGNORE_TABLESPACE)) { dberr_t err= lock_table_for_trx(table, trx, LOCK_X); /* Wait for purge threads to stop using the table. */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index df17f2b6359..85a4ce90d90 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4547,6 +4547,10 @@ innobase_commit( SQL statement */ trx_mark_sql_stat_end(trx); + if (UNIV_UNLIKELY(trx->error_state != DB_SUCCESS)) { + trx_rollback_for_mysql(trx); + DBUG_RETURN(1); + } } /* Reset the number AUTO-INC rows required */ @@ -18883,11 +18887,6 @@ static MYSQL_SYSVAR_ENUM(flush_method, srv_file_flush_method, NULL, NULL, IF_WIN(SRV_ALL_O_DIRECT_FSYNC, SRV_O_DIRECT), &innodb_flush_method_typelib); -static MYSQL_SYSVAR_BOOL(force_load_corrupted, srv_load_corrupted, - PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, - "Force InnoDB to load metadata of corrupted table.", - NULL, NULL, FALSE); - static MYSQL_SYSVAR_STR(log_group_home_dir, srv_log_group_home_dir, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "Path to InnoDB log files.", NULL, NULL, NULL); @@ -19785,7 +19784,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(ft_min_token_size), MYSQL_SYSVAR(ft_num_word_optimize), MYSQL_SYSVAR(ft_sort_pll_degree), - MYSQL_SYSVAR(force_load_corrupted), MYSQL_SYSVAR(lock_wait_timeout), MYSQL_SYSVAR(deadlock_detect), MYSQL_SYSVAR(deadlock_report), diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 5d73b16e06b..a63c6642010 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -341,8 +341,6 @@ static buf_block_t *ibuf_tree_root_get(mtr_t *mtr) page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO), 0, RW_SX_LATCH, mtr); - ut_ad(page_get_space_id(block->frame) == IBUF_SPACE_ID); - ut_ad(page_get_page_no(block->frame) == FSP_IBUF_TREE_ROOT_PAGE_NO); ut_ad(ibuf.empty == page_is_empty(block->frame)); return block; diff --git a/storage/innobase/include/btr0cur.ic b/storage/innobase/include/btr0cur.ic index 8a45b714936..905dc28bd62 100644 --- a/storage/innobase/include/btr0cur.ic +++ b/storage/innobase/include/btr0cur.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2020, MariaDB Corporation. +Copyright (c) 2018, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -109,10 +109,7 @@ btr_cur_position( buf_block_t* block, /*!< in: buffer block of rec */ btr_cur_t* cursor) /*!< out: cursor */ { - ut_ad(page_align(rec) == block->frame); - page_cur_position(rec, block, btr_cur_get_page_cur(cursor)); - cursor->index = index; } diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h index 9a53ecdab8f..104e99fc0cd 100644 --- a/storage/innobase/include/dict0types.h +++ b/storage/innobase/include/dict0types.h @@ -71,18 +71,20 @@ enum dict_err_ignore_t { DICT_ERR_IGNORE_NONE = 0, /*!< no error to ignore */ DICT_ERR_IGNORE_FK_NOKEY = 1, /*!< ignore error if any foreign key is missing */ - DICT_ERR_IGNORE_INDEX_ROOT = 2, /*!< ignore error if index root - page is FIL_NULL or incorrect value */ - DICT_ERR_IGNORE_CORRUPT = 4, /*!< skip corrupted indexes */ - DICT_ERR_IGNORE_RECOVER_LOCK = 8, + DICT_ERR_IGNORE_INDEX = 2, /*!< ignore corrupted indexes */ + DICT_ERR_IGNORE_RECOVER_LOCK = 4, /*!< Used when recovering table locks for resurrected transactions. Silently load a missing tablespace, and do not load incomplete index definitions. */ /** ignore all errors above */ - DICT_ERR_IGNORE_ALL = 15, - /** prepare to drop the table; do not attempt to load tablespace */ + DICT_ERR_IGNORE_ALL = 7, + /** prepare some DDL operation; + do not attempt to load tablespace */ + DICT_ERR_IGNORE_TABLESPACE = 15, + /** prepare to drop the table; do not attempt to load tablespace + or the metadata */ DICT_ERR_IGNORE_DROP = 31 }; diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 6dbcfa7c54d..ef98b53e0cc 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -307,11 +307,6 @@ void innodb_wait_allow_writes(); # define innodb_wait_allow_writes() do {} while (0) #endif /* WITH_INNODB_DISALLOW_WRITES */ -/* If this flag is TRUE, then we will load the indexes' (and tables') metadata -even if they are marked as "corrupted". Mostly it is for DBA to process -corrupted index and table */ -extern my_bool srv_load_corrupted; - /** Requested size in bytes */ extern ulint srv_buf_pool_size; /** Minimum pool size in bytes */ diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 3a63749695a..4c73cb1202d 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -1195,6 +1195,8 @@ void mtr_t::page_lock(buf_block_t *block, ulint rw_latch) #endif /* BTR_CUR_HASH_ADAPT */ done: + ut_ad(page_id_t(page_get_space_id(block->frame), + page_get_page_no(block->frame)) == block->page.id()); memo_push(block, fix_type); } |