Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-41675

Crash when using ROW_FORMAT=COMPRESSED on table with spatial index

    XMLWordPrintable

Details

    • Can result in hang or crash
    • Q4/2026 Server Development

    Description

      Inserting into a SPATIAL index can crash the server with SIGSEGV in rtr_ins_enlarge_mbr().
      This happened to me when using an ALTER TABLE t ROW_FORMAT=COMPRESSED; statement on a large table with a spatial index.

      Backtrace of the test case below on an unpatched 10.11 debug build:

      mariadbd got signal 11 ;
      Server version: 10.11.19-MariaDB-debug-log
      bits/stl_vector.h:1224(std::vector<node_visit_t, ut_allocator<node_visit_t, true> >::empty() const)
      gis/gis0rtree.cc:1248(rtr_ins_enlarge_mbr(btr_cur_t*, mtr_t*))
      row/row0merge.cc:209(spatial_index_info::insert(unsigned long, btr_pcur_t*, bool&, mem_block_info_t*, mtr_t*))
      row/row0merge.cc:1766(row_merge_spatial_rows(unsigned long, spatial_index_info**, unsigned long, mem_block_info_t*, btr_pcur_t*, bool&, mtr_t*))
      row/row0merge.cc:2161(row_merge_read_clustered_index(...))
      row/row0merge.cc:4782(row_merge_build_indexes(...))
      handler/handler0alter.cc:8972(ha_innobase::inplace_alter_table(TABLE*, Alter_inplace_info*))
      sql/handler.h:4626(handler::ha_inplace_alter_table(TABLE*, Alter_inplace_info*))
      sql/sql_table.cc:8229(mysql_inplace_alter_table(...))
      sql/sql_table.cc:11575(mysql_alter_table(...))
      sql/sql_alter.cc:688(Sql_cmd_alter_table::execute(THD*))
      sql/sql_parse.cc:6190(mysql_execute_command(THD*, bool))
      

      MySQL fixed this in 8.0.18 as Bug#28569379 ("ASSERTION FAILURE: SYNC0POLICY.IC.*:M_CONTEXT.M_THREAD_ID == OS_THREAD_ID", commit dcc57a42d1f)

      Patch against 10.11 (the DBUG injection point for the test is included) (thanks Claude AI):

      diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc
      index 47611e8df83..b4350d2c809 100644
      --- a/storage/innobase/gis/gis0rtree.cc
      +++ b/storage/innobase/gis/gis0rtree.cc
      @@ -629,6 +629,7 @@ rtr_adjust_upper_level(
       
       	if (err == DB_FAIL) {
       		cursor.rtr_info = sea_cur->rtr_info;
      +		cursor.rtr_info_borrowed = true;
       		cursor.tree_height = sea_cur->tree_height;
       
       		/* Recreate a memory heap as input parameter for
      @@ -1128,6 +1129,11 @@ rtr_page_split_and_insert(
       				rec = NULL;
       				goto after_insert; }
       	);
      +	DBUG_EXECUTE_IF("rtr_nonleaf_page_need_second_split",
      +			if (!iterated && page_level) {
      +				rec = NULL;
      +				goto after_insert; }
      +	);
       
       	rec = page_cur_tuple_insert(page_cursor, tuple,
       				    offsets, heap, n_ext, mtr);
      @@ -1189,10 +1195,14 @@ rtr_page_split_and_insert(
       			ibuf_reset_free_bits(block);
       		}
       
      -		/* We need to clean the parent path here and search father
      -		node later, otherwise, it's possible that find a wrong
      -		parent. */
      -		rtr_clean_rtr_info(cursor->rtr_info, true);
      +		if (!cursor->rtr_info_borrowed) {
      +			/* We need to clean the parent path here and
      +			search father node later, otherwise, it's
      +			possible that find a wrong parent. The search
      +			path of a borrowed rtr_info is still used by
      +			its owner. */
      +			rtr_clean_rtr_info(cursor->rtr_info, true);
      +		}
       		cursor->rtr_info = NULL;
       		IF_DBUG(iterated=true,);
       
      diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc
      index 0c0843a978a..60c8b9a582d 100644
      --- a/storage/innobase/gis/gis0sea.cc
      +++ b/storage/innobase/gis/gis0sea.cc
      @@ -1153,6 +1153,7 @@ static const rec_t* rtr_get_father_node(
       					  btr_pcur_get_block(r_cursor),
       					  btr_cur_get_page_cur(btr_cur));
       			had_rtr = btr_cur->rtr_info = sea_cur->rtr_info;
      +			btr_cur->rtr_info_borrowed = true;
       			btr_cur->tree_height = sea_cur->tree_height;
       		}
       		goto func_exit;
      @@ -1167,6 +1168,7 @@ static const rec_t* rtr_get_father_node(
       	}
       
       	btr_cur->rtr_info = rtr_create_rtr_info(false, false, btr_cur, index);
      +	btr_cur->rtr_info_borrowed = false;
       
       	if (rtr_search_to_nth_level(level, tuple, PAGE_CUR_RTREE_LOCATE,
       				    BTR_CONT_MODIFY_TREE, btr_cur, mtr)
      diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
      index 935be505436..520de3f24c8 100644
      --- a/storage/innobase/include/btr0cur.h
      +++ b/storage/innobase/include/btr0cur.h
      @@ -731,6 +731,9 @@ struct btr_cur_t {
       					flag is BTR_CUR_HASH */
       	/* @} */
       	rtr_info_t*	rtr_info;	/*!< rtree search info */
      +	/** whether rtr_info is owned by another cursor, which will
      +	clean it up */
      +	bool		rtr_info_borrowed;
         btr_cur_t() { memset((void*) this, 0, sizeof *this); }
       
         dict_index_t *index() const { return page_cur.index; }
      

      Attachments

        Activity

          People

            tafzeel Mohammad Tafzeel Shams
            M393 Maximilian Krög
            Thirunarayanan Balathandayuthapani Thirunarayanan Balathandayuthapani
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Time Tracking

                Estimated:
                Original Estimate - 0d
                0d
                Remaining:
                Remaining Estimate - 0.5d
                0.5d
                Logged:
                Time Spent - Not Specified
                Not Specified

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.