[MDEV-30106] InnoDB fails to validate the change buffer on startup Created: 2022-11-28  Updated: 2023-03-09  Resolved: 2022-11-28

Status: Closed
Project: MariaDB Server
Component/s: Storage Engine - InnoDB
Affects Version/s: 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 10.10, 10.11
Fix Version/s: 10.11.2, 10.5.19, 10.6.12, 10.7.8, 10.8.7, 10.9.5, 10.10.3

Type: Bug Priority: Blocker
Reporter: Marko Mäkelä Assignee: Marko Mäkelä
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
Blocks
blocks MDEV-29694 Remove the InnoDB change buffer Closed
Problem/Incident
causes MDEV-30819 InnoDB fails to start up after downgr... Closed

 Description   

The function ibuf_init_at_db_start() fails to validate the contents of the root page of the change buffer tree, beyond checking that the page checksum is valid.

Should the page exist but be in a different format (such as a dummy page created after MDEV-29694 removed the change buffer), InnoDB would crash on some DDL operations or on slow shutdown when trying to access the change buffer tree.

Here is how the change buffer creation can be disabled on startup:

diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 8e291352d55..3f81f33cee1 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1401,17 +1401,48 @@ dberr_t srv_start(bool create_new_db)
 				     uint32_t(sum_of_new_sizes), &mtr)
 		     == DB_SUCCESS);
 
+#if 1
 		ulint ibuf_root = btr_create(
 			DICT_CLUSTERED | DICT_IBUF, fil_system.sys_space,
 			DICT_IBUF_ID_MIN, nullptr, &mtr, &err);
+#else
+		/* Allocate dummy change buffer pages for backward
+		compatibility and to prevent a downgrade. */
+		if (err != DB_SUCCESS) {
+		} else if (buf_block_t *b =
+			   fseg_create(fil_system.sys_space, PAGE_DATA, &mtr,
+				       &err)) {
+			ut_ad(b->page.id()
+			      == page_id_t(0, FSP_IBUF_HEADER_PAGE_NO));
+			b = fseg_alloc_free_page_general(
+				b->page.frame + PAGE_DATA,
+				FSP_IBUF_TREE_ROOT_PAGE_NO, FSP_UP, false,
+				&mtr, &mtr, &err);
+			if (b) {
+				ut_ad(b->page.id() == page_id_t
+				      (0, FSP_IBUF_TREE_ROOT_PAGE_NO));
+				mtr.set_modified(*b);
+				fsp_init_file_page(fil_system.sys_space, b,
+						   &mtr);
+			} else {
+				ut_ad(err != DB_SUCCESS);
+			}
+		}
+#endif
 
 		mtr_commit(&mtr);
 
+#if 1
 		if (ibuf_root == FIL_NULL) {
 			return srv_init_abort(err);
 		}
 
 		ut_ad(ibuf_root == IBUF_TREE_ROOT_PAGE_NO);
+#else
+		if (err != DB_SUCCESS) {
+			return srv_init_abort(err);
+		}
+#endif
 
 		/* To maintain backward compatibility we create only
 		the first rollback segment before the double write buffer.

A proper validation of the change buffer on startup is necessary so that attempts to downgrade from newer major releases that include MDEV-29694 can be prevented.


Generated at Thu Feb 08 10:13:42 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.