Commit 313c5a1d authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-31443 [FATAL] InnoDB: Unable to find charset-collation in ibuf_upgrade()

dtype_new_read_for_order_and_null_size(): Correctly assign type->prtype.
This caused the fatal error and crash.

ibuf_merge(): Relax a too strict condition that would result in
[ERROR] InnoDB: Unable to upgrade the change buffer
when there exist buffered changes to redundant secondary indexes, such as
PRIMARY KEY(x), INDEX(x).

ibuf_upgrade(): Modify at most one user tablespace per mini-transaction,
to be crash-safe.

page_cur_insert_rec_zip(), page_cur_delete_rec(): Relax debug assertions
for ibuf_upgrade().

ibuf_log_rebuild_if_needed(): Invoke recv_sys.debug_free() only after
srv_log_rebuild_if_needed() to avoid an assertion failure. This code
is executed when the innodb_log_file_size is changed when upgrading
from 10.x to 11.0.

Tested by: Matthias Leich, Christian Hesse
parent a906046f
...@@ -156,7 +156,7 @@ dtype_new_read_for_order_and_null_size( ...@@ -156,7 +156,7 @@ dtype_new_read_for_order_and_null_size(
<< 16; << 16;
if (dtype_is_string_type(type->mtype)) { if (dtype_is_string_type(type->mtype)) {
type->prtype |= charset_coll << 16; type->prtype |= charset_coll;
if (charset_coll == 0) { if (charset_coll == 0) {
/* This insert buffer record was inserted before /* This insert buffer record was inserted before
...@@ -709,7 +709,7 @@ static dberr_t ibuf_merge(fil_space_t *space, btr_cur_t *cur, mtr_t *mtr) ...@@ -709,7 +709,7 @@ static dberr_t ibuf_merge(fil_space_t *space, btr_cur_t *cur, mtr_t *mtr)
rec_t *rec= cur->page_cur.rec; rec_t *rec= cur->page_cur.rec;
ulint n_fields= rec_get_n_fields_old(rec); ulint n_fields= rec_get_n_fields_old(rec);
if (n_fields <= IBUF_REC_FIELD_USER + 1 || rec[4]) if (n_fields < IBUF_REC_FIELD_USER + 1 || rec[4])
return DB_CORRUPTION; return DB_CORRUPTION;
n_fields-= IBUF_REC_FIELD_USER; n_fields-= IBUF_REC_FIELD_USER;
...@@ -910,7 +910,17 @@ ATTRIBUTE_COLD dberr_t ibuf_upgrade() ...@@ -910,7 +910,17 @@ ATTRIBUTE_COLD dberr_t ibuf_upgrade()
prev_space_id= space_id; prev_space_id= space_id;
space= fil_space_t::get(space_id); space= fil_space_t::get(space_id);
if (space) if (space)
{
/* Move to the next user tablespace. We buffer-fix the current
change buffer leaf page to prevent it from being evicted
before we have started a new mini-transaction. */
cur.page_cur.block->fix();
mtr.commit();
log_free_check();
mtr.start();
mtr.page_lock(cur.page_cur.block, RW_X_LATCH);
mtr.set_named_space(space); mtr.set_named_space(space);
}
spaces++; spaces++;
} }
pages++; pages++;
......
...@@ -1791,7 +1791,8 @@ page_cur_insert_rec_zip( ...@@ -1791,7 +1791,8 @@ page_cur_insert_rec_zip(
ut_ad(rec_offs_comp(offsets)); ut_ad(rec_offs_comp(offsets));
ut_ad(fil_page_get_type(page) == FIL_PAGE_INDEX || ut_ad(fil_page_get_type(page) == FIL_PAGE_INDEX ||
fil_page_get_type(page) == FIL_PAGE_RTREE); fil_page_get_type(page) == FIL_PAGE_RTREE);
ut_ad(mach_read_from_8(PAGE_HEADER + PAGE_INDEX_ID + page) == index->id); ut_ad(mach_read_from_8(PAGE_HEADER + PAGE_INDEX_ID + page) == index->id ||
index->is_dummy);
ut_ad(!page_get_instant(page)); ut_ad(!page_get_instant(page));
ut_ad(!page_cur_is_after_last(cursor)); ut_ad(!page_cur_is_after_last(cursor));
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
...@@ -2258,7 +2259,7 @@ page_cur_delete_rec( ...@@ -2258,7 +2259,7 @@ page_cur_delete_rec(
== index->table->not_redundant()); == index->table->not_redundant());
ut_ad(fil_page_index_page_check(block->page.frame)); ut_ad(fil_page_index_page_check(block->page.frame));
ut_ad(mach_read_from_8(PAGE_HEADER + PAGE_INDEX_ID + block->page.frame) ut_ad(mach_read_from_8(PAGE_HEADER + PAGE_INDEX_ID + block->page.frame)
== index->id); == index->id || index->is_dummy);
ut_ad(mtr->is_named_space(index->table->space)); ut_ad(mtr->is_named_space(index->table->space));
/* The record must not be the supremum or infimum record. */ /* The record must not be the supremum or infimum record. */
......
...@@ -1165,8 +1165,9 @@ ATTRIBUTE_COLD static dberr_t ibuf_log_rebuild_if_needed() ...@@ -1165,8 +1165,9 @@ ATTRIBUTE_COLD static dberr_t ibuf_log_rebuild_if_needed()
if (recv_sys.is_corrupt_log() || recv_sys.is_corrupt_fs()) if (recv_sys.is_corrupt_log() || recv_sys.is_corrupt_fs())
return DB_CORRUPTION; return DB_CORRUPTION;
dberr_t err= srv_log_rebuild_if_needed();
recv_sys.debug_free(); recv_sys.debug_free();
return srv_log_rebuild_if_needed(); return err;
} }
static tpool::task_group rollback_all_recovered_group(1); static tpool::task_group rollback_all_recovered_group(1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment