mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
MDEV-30106 InnoDB fails to validate the change buffer on startup
ibuf_init_at_db_start(): Validate the change buffer root page. A later version may stop creating a change buffer, and this validation check will prevent a downgrade from such later versions. ibuf_max_size_update(): If the change buffer was not loaded, do nothing. dict_boot(): Merge the local variable "error" to "err". Ignore failures of ibuf_init_at_db_start() if innodb_force_recovery>=4.
This commit is contained in:
@@ -19,6 +19,7 @@ call mtr.add_suppression("InnoDB: Obtaining redo log encryption key version 1 fa
|
||||
call mtr.add_suppression("InnoDB: Decrypting checkpoint failed");
|
||||
call mtr.add_suppression("InnoDB: Are you sure you are using the right ib_logfile0 to start up the database\\? Log sequence number in the ib_logfile0 is 1213964,");
|
||||
call mtr.add_suppression("InnoDB: Log file .*ib_logfile1 is of different size 1048576 bytes than other log files 2097152 bytes!");
|
||||
call mtr.add_suppression("InnoDB: The change buffer is corrupted");
|
||||
--enable_query_log
|
||||
|
||||
let bugdir= $MYSQLTEST_VARDIR/tmp/log_corruption;
|
||||
|
||||
@@ -313,9 +313,9 @@ dict_boot(void)
|
||||
dict_mem_index_add_field(index, "NAME", 0);
|
||||
|
||||
index->id = DICT_TABLES_ID;
|
||||
dberr_t error = dict_index_add_to_cache(
|
||||
dberr_t err = dict_index_add_to_cache(
|
||||
index, mach_read_from_4(dict_hdr + DICT_HDR_TABLES));
|
||||
ut_a(error == DB_SUCCESS);
|
||||
ut_a(err == DB_SUCCESS);
|
||||
ut_ad(!table->is_instant());
|
||||
table->indexes.start->n_core_null_bytes = static_cast<uint8_t>(
|
||||
UT_BITS_IN_BYTES(unsigned(table->indexes.start->n_nullable)));
|
||||
@@ -325,9 +325,9 @@ dict_boot(void)
|
||||
dict_mem_index_add_field(index, "ID", 0);
|
||||
|
||||
index->id = DICT_TABLE_IDS_ID;
|
||||
error = dict_index_add_to_cache(
|
||||
err = dict_index_add_to_cache(
|
||||
index, mach_read_from_4(dict_hdr + DICT_HDR_TABLE_IDS));
|
||||
ut_a(error == DB_SUCCESS);
|
||||
ut_a(err == DB_SUCCESS);
|
||||
|
||||
/*-------------------------*/
|
||||
table = dict_mem_table_create("SYS_COLUMNS", fil_system.sys_space,
|
||||
@@ -355,9 +355,9 @@ dict_boot(void)
|
||||
dict_mem_index_add_field(index, "POS", 0);
|
||||
|
||||
index->id = DICT_COLUMNS_ID;
|
||||
error = dict_index_add_to_cache(
|
||||
err = dict_index_add_to_cache(
|
||||
index, mach_read_from_4(dict_hdr + DICT_HDR_COLUMNS));
|
||||
ut_a(error == DB_SUCCESS);
|
||||
ut_a(err == DB_SUCCESS);
|
||||
ut_ad(!table->is_instant());
|
||||
table->indexes.start->n_core_null_bytes = static_cast<uint8_t>(
|
||||
UT_BITS_IN_BYTES(unsigned(table->indexes.start->n_nullable)));
|
||||
@@ -398,9 +398,9 @@ dict_boot(void)
|
||||
dict_mem_index_add_field(index, "ID", 0);
|
||||
|
||||
index->id = DICT_INDEXES_ID;
|
||||
error = dict_index_add_to_cache(
|
||||
err = dict_index_add_to_cache(
|
||||
index, mach_read_from_4(dict_hdr + DICT_HDR_INDEXES));
|
||||
ut_a(error == DB_SUCCESS);
|
||||
ut_a(err == DB_SUCCESS);
|
||||
ut_ad(!table->is_instant());
|
||||
table->indexes.start->n_core_null_bytes = static_cast<uint8_t>(
|
||||
UT_BITS_IN_BYTES(unsigned(table->indexes.start->n_nullable)));
|
||||
@@ -427,9 +427,9 @@ dict_boot(void)
|
||||
dict_mem_index_add_field(index, "POS", 0);
|
||||
|
||||
index->id = DICT_FIELDS_ID;
|
||||
error = dict_index_add_to_cache(
|
||||
err = dict_index_add_to_cache(
|
||||
index, mach_read_from_4(dict_hdr + DICT_HDR_FIELDS));
|
||||
ut_a(error == DB_SUCCESS);
|
||||
ut_a(err == DB_SUCCESS);
|
||||
ut_ad(!table->is_instant());
|
||||
table->indexes.start->n_core_null_bytes = static_cast<uint8_t>(
|
||||
UT_BITS_IN_BYTES(unsigned(table->indexes.start->n_nullable)));
|
||||
@@ -440,9 +440,11 @@ dict_boot(void)
|
||||
|
||||
/* Initialize the insert buffer table and index for each tablespace */
|
||||
|
||||
dberr_t err = ibuf_init_at_db_start();
|
||||
err = ibuf_init_at_db_start();
|
||||
|
||||
if (err == DB_SUCCESS) {
|
||||
if (err == DB_SUCCESS
|
||||
|| srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
|
||||
err = DB_SUCCESS;
|
||||
/* Load definitions of other indexes on system tables */
|
||||
|
||||
dict_load_sys_table(dict_sys.sys_tables);
|
||||
|
||||
@@ -50,6 +50,7 @@ Created 7/19/1997 Heikki Tuuri
|
||||
#include "que0que.h"
|
||||
#include "srv0start.h" /* srv_shutdown_state */
|
||||
#include "rem0cmp.h"
|
||||
#include "log.h"
|
||||
|
||||
/* STRUCTURE OF AN INSERT BUFFER RECORD
|
||||
|
||||
@@ -408,21 +409,54 @@ ibuf_init_at_db_start(void)
|
||||
ulint n_used;
|
||||
|
||||
ut_ad(!ibuf.index);
|
||||
dberr_t err;
|
||||
mtr_t mtr;
|
||||
mtr.start();
|
||||
compile_time_assert(IBUF_SPACE_ID == TRX_SYS_SPACE);
|
||||
compile_time_assert(IBUF_SPACE_ID == 0);
|
||||
mtr_x_lock_space(fil_system.sys_space, &mtr);
|
||||
buf_block_t* header_page = buf_page_get(
|
||||
buf_block_t* header_page = buf_page_get_gen(
|
||||
page_id_t(IBUF_SPACE_ID, FSP_IBUF_HEADER_PAGE_NO),
|
||||
0, RW_X_LATCH, &mtr);
|
||||
0, RW_X_LATCH, nullptr, BUF_GET,
|
||||
__FILE__, __LINE__, &mtr, &err);
|
||||
|
||||
if (!header_page) {
|
||||
err_exit:
|
||||
sql_print_error("InnoDB: The change buffer is corrupted");
|
||||
mtr.commit();
|
||||
return DB_DECRYPTION_FAILED;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* At startup we intialize ibuf to have a maximum of
|
||||
fseg_n_reserved_pages(*header_page,
|
||||
IBUF_HEADER + IBUF_TREE_SEG_HEADER
|
||||
+ header_page->frame, &n_used, &mtr);
|
||||
|
||||
ut_ad(n_used >= 2);
|
||||
|
||||
ibuf.seg_size = n_used;
|
||||
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
block = buf_page_get_gen(
|
||||
page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO),
|
||||
0, RW_X_LATCH, nullptr, BUF_GET,
|
||||
__FILE__, __LINE__, &mtr, &err);
|
||||
|
||||
if (!block) goto err_exit;
|
||||
|
||||
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
|
||||
|
||||
root = buf_block_get_frame(block);
|
||||
}
|
||||
|
||||
if (page_is_comp(root) || fil_page_get_type(root) != FIL_PAGE_INDEX
|
||||
|| btr_page_get_index_id(root) != DICT_IBUF_ID_MIN) {
|
||||
err = DB_CORRUPTION;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
/* At startup we initialize ibuf to have a maximum of
|
||||
CHANGE_BUFFER_DEFAULT_SIZE in terms of percentage of the
|
||||
buffer pool size. Once ibuf struct is initialized this
|
||||
value is updated with the user supplied size by calling
|
||||
@@ -437,26 +471,6 @@ ibuf_init_at_db_start(void)
|
||||
|
||||
mutex_enter(&ibuf_mutex);
|
||||
|
||||
fseg_n_reserved_pages(*header_page,
|
||||
IBUF_HEADER + IBUF_TREE_SEG_HEADER
|
||||
+ header_page->frame, &n_used, &mtr);
|
||||
|
||||
ut_ad(n_used >= 2);
|
||||
|
||||
ibuf.seg_size = n_used;
|
||||
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
block = buf_page_get(
|
||||
page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO),
|
||||
0, RW_X_LATCH, &mtr);
|
||||
|
||||
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
|
||||
|
||||
root = buf_block_get_frame(block);
|
||||
}
|
||||
|
||||
ibuf_size_update(root);
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
@@ -507,6 +521,7 @@ ibuf_max_size_update(
|
||||
ulint new_val) /*!< in: new value in terms of
|
||||
percentage of the buffer pool size */
|
||||
{
|
||||
if (UNIV_UNLIKELY(!ibuf.index)) return;
|
||||
ulint new_size = ((buf_pool_get_curr_size() >> srv_page_size_shift)
|
||||
* new_val) / 100;
|
||||
mutex_enter(&ibuf_mutex);
|
||||
|
||||
@@ -2056,7 +2056,8 @@ void innodb_shutdown()
|
||||
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
|
||||
ut_ad(lock_sys.is_initialised() || !srv_was_started);
|
||||
ut_ad(log_sys.is_initialised() || !srv_was_started);
|
||||
ut_ad(ibuf.index || !srv_was_started);
|
||||
ut_ad(ibuf.index || !srv_was_started
|
||||
|| srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE);
|
||||
|
||||
dict_stats_deinit();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user