summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2023-03-09 16:16:58 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2023-03-09 16:16:58 +0200
commit08267ba0c88d2f3ba1bacee9bb9a1e4da921a60a (patch)
tree486a8cf5e0f672a33488e63927eb8cc3db9a2fdb
parent231c0eb7a68570da6b5b3741b2f1431c2f43c475 (diff)
downloadmariadb-git-08267ba0c88d2f3ba1bacee9bb9a1e4da921a60a.tar.gz
MDEV-30819 InnoDB fails to start up after downgrading from MariaDB 11.0
While downgrades are not supported and misguided attempts at it could cause serious corruption especially after commit b07920b634f455c39e3650c6163bec2a8ce0ffe0 it might be useful if InnoDB would start up even after an upgrade to MariaDB Server 11.0 or later had removed the change buffer. innodb_change_buffering_update(): Disallow anything else than innodb_change_buffering=none when the change buffer is corrupted. ibuf_init_at_db_start(): Mention a possible downgrade in the corruption error message. If innodb_change_buffering=none, ignore the error but do not initialize ibuf.index. ibuf_free_excess_pages(), ibuf_contract(), ibuf_merge_space(), ibuf_update_max_tablespace_id(), ibuf_delete_for_discarded_space(), ibuf_print(): Check for !ibuf.index. ibuf_check_bitmap_on_import(): Remove some unnecessary code. This function is only accessing change buffer bitmap pages in a data file that is not attached to the rest of the database. It is not accessing the change buffer tree itself, hence it does not need any additional mutex protection. This has been tested both by starting up MariaDB Server 10.8 on a 11.0 data directory, and by running ./mtr --big-test while ibuf_init_at_db_start() was tweaked to always fail.
-rw-r--r--storage/innobase/handler/ha_innodb.cc14
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc26
-rw-r--r--storage/innobase/srv/srv0start.cc2
3 files changed, 28 insertions, 14 deletions
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index f359f843049..ef7b8e51794 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -19719,10 +19719,22 @@ static MYSQL_SYSVAR_BOOL(numa_interleave, srv_numa_interleave,
NULL, NULL, FALSE);
#endif /* HAVE_LIBNUMA */
+static void innodb_change_buffering_update(THD *thd, struct st_mysql_sys_var*,
+ void*, const void *save)
+{
+ ulong i= *static_cast<const ulong*>(save);
+ if (i != IBUF_USE_NONE && !ibuf.index)
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_NOT_KEYFILE,
+ "InnoDB: The change buffer is corrupted.");
+ else
+ innodb_change_buffering= i;
+}
+
static MYSQL_SYSVAR_ENUM(change_buffering, innodb_change_buffering,
PLUGIN_VAR_RQCMDARG,
"Buffer changes to secondary indexes.",
- NULL, NULL, IBUF_USE_NONE, &innodb_change_buffering_typelib);
+ nullptr, innodb_change_buffering_update,
+ IBUF_USE_NONE, &innodb_change_buffering_typelib);
static MYSQL_SYSVAR_UINT(change_buffer_max_size,
srv_change_buffer_max_size,
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index dff0ad57057..fc97aabfa13 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -422,8 +422,13 @@ ibuf_init_at_db_start(void)
if (!header_page) {
err_exit:
- sql_print_error("InnoDB: The change buffer is corrupted");
+ sql_print_error("InnoDB: The change buffer is corrupted"
+ " or has been removed on upgrade"
+ " to MariaDB 11.0 or later");
mtr.commit();
+ if (innodb_change_buffering == IBUF_USE_NONE) {
+ err = DB_SUCCESS;
+ }
return err;
}
@@ -2002,6 +2007,7 @@ void
ibuf_free_excess_pages(void)
/*========================*/
{
+ if (UNIV_UNLIKELY(!ibuf.index)) return;
/* Free at most a few pages at a time, so that we do not delay the
requested service too much */
@@ -2439,6 +2445,7 @@ will be merged from ibuf trees to the pages read
@retval 0 if ibuf.empty */
ulint ibuf_contract()
{
+ if (UNIV_UNLIKELY(!ibuf.index)) return 0;
mtr_t mtr;
btr_pcur_t pcur;
ulint sum_sizes;
@@ -2494,6 +2501,7 @@ ibuf_merge_space(
/*=============*/
ulint space) /*!< in: tablespace id to merge */
{
+ if (UNIV_UNLIKELY(!ibuf.index)) return 0;
mtr_t mtr;
btr_pcur_t pcur;
@@ -2952,6 +2960,7 @@ void
ibuf_update_max_tablespace_id(void)
/*===============================*/
{
+ if (UNIV_UNLIKELY(!ibuf.index)) return;
ulint max_space_id;
const rec_t* rec;
const byte* field;
@@ -2959,7 +2968,7 @@ ibuf_update_max_tablespace_id(void)
btr_pcur_t pcur;
mtr_t mtr;
- ut_a(!dict_table_is_comp(ibuf.index->table));
+ ut_ad(!ibuf.index->table->not_redundant());
ibuf_mtr_start(&mtr);
@@ -4499,6 +4508,8 @@ in DISCARD TABLESPACE, IMPORT TABLESPACE, or read-ahead.
@param[in] space missing or to-be-discarded tablespace */
void ibuf_delete_for_discarded_space(ulint space)
{
+ if (UNIV_UNLIKELY(!ibuf.index)) return;
+
btr_pcur_t pcur;
const rec_t* ibuf_rec;
mtr_t mtr;
@@ -4608,6 +4619,7 @@ ibuf_print(
/*=======*/
FILE* file) /*!< in: file where to print */
{
+ if (UNIV_UNLIKELY(!ibuf.index)) return;
mutex_enter(&ibuf_mutex);
fprintf(file,
@@ -4647,8 +4659,6 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
mtr_t mtr;
- mutex_enter(&ibuf_mutex);
-
/* The two bitmap pages (allocation bitmap and ibuf bitmap) repeat
every page_size pages. For example if page_size is 16 KiB, then the
two bitmap pages repeat every 16 KiB * 16384 = 256 MiB. In the loop
@@ -4657,17 +4667,14 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
for (uint32_t page_no = 0; page_no < size; page_no += physical_size) {
if (trx_is_interrupted(trx)) {
- mutex_exit(&ibuf_mutex);
return(DB_INTERRUPTED);
}
mtr_start(&mtr);
- ibuf_enter(&mtr);
buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
page_id_t(space->id, page_no), zip_size, &mtr);
if (!bitmap_page) {
- mutex_exit(&ibuf_mutex);
mtr.commit();
return DB_CORRUPTION;
}
@@ -4690,7 +4697,6 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
physical_size)));
}
#endif /* UNIV_DEBUG */
- ibuf_exit(&mtr);
mtr_commit(&mtr);
continue;
}
@@ -4704,8 +4710,6 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
bitmap_page->frame, cur_page_id, zip_size,
IBUF_BITMAP_IBUF, &mtr)) {
- mutex_exit(&ibuf_mutex);
- ibuf_exit(&mtr);
mtr_commit(&mtr);
ib_errf(trx->mysql_thd,
@@ -4738,11 +4742,9 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
}
}
- ibuf_exit(&mtr);
mtr_commit(&mtr);
}
- mutex_exit(&ibuf_mutex);
return(DB_SUCCESS);
}
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 311a01ed719..f56f2846872 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -2046,7 +2046,7 @@ 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 || !innodb_change_buffering || !srv_was_started
|| srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE);
dict_stats_deinit();