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

SIGFPE and/or huge memory allocation in maria_create with distinct/group by/ rollup

Details

    • Bug
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Fixed
    • 10.2.1
    • 10.2.4
    • Optimizer
    • windows x64, linux x64
    • 10.2.4-3, 10.2.4-1, 10.2.4-2

    Description

      Version: '10.2.1-MariaDB'  socket: ''  port: 3306  mariadb.org binary distribution
      [ERROR] mysqld got exception 0xc0000005 ;
      mysqld.exe!maria_create()[ma_create.c:163]
      mysqld.exe!create_internal_tmp_table()[sql_select.cc:17280]
      mysqld.exe!create_internal_tmp_table_from_heap()[sql_select.cc:17511]
      mysqld.exe!JOIN::rollup_write_data()[sql_select.cc:23765]
      mysqld.exe!end_write_group()[sql_select.cc:19930]
      mysqld.exe!AGGR_OP::end_send()[sql_select.cc:26133]
      mysqld.exe!sub_select_postjoin_aggr()[sql_select.cc:18016]
      mysqld.exe!do_select()[sql_select.cc:17845]
      mysqld.exe!JOIN::exec_inner()[sql_select.cc:3343]
      mysqld.exe!JOIN::exec()[sql_select.cc:3154]
      mysqld.exe!mysql_select()[sql_select.cc:3539]
      mysqld.exe!handle_select()[sql_select.cc:377]
      mysqld.exe!execute_sqlcom_select()[sql_parse.cc:6309]
      mysqld.exe!mysql_execute_command()[sql_parse.cc:3352]
      mysqld.exe!mysql_parse()[sql_parse.cc:7746]
      mysqld.exe!dispatch_command()[sql_parse.cc:1793]
      mysqld.exe!do_command()[sql_parse.cc:1353]
      mysqld.exe!threadpool_process_request()[threadpool_common.cc:252]
      mysqld.exe!io_completion_callback()[threadpool_win.cc:462]
      

      How to repeat
      ------------------

      drop table if exists t;
      create table t (a int,b int) engine=innodb;
      insert into t values(-126,7),(1,1),(0,0),(-1,1),(351,65534);
      select distinct 1 from t group by a,b with rollup limit 1;
      

      Attachments

        Issue Links

          Activity

            In the function JOIN::create_postjoin_aggr_table in sql_select.cc, the tmp_table_param field is not updated by the new values of the tab->tmp_table_param.

            TABLE* table= create_tmp_table(thd, tab->tmp_table_param, *table_fields,
                                             table_group, distinct,
                                             save_sum_fields, select_options, table_rows_limit, 
                                             "", true, keep_row_order);
            

            the tab->tmp_table_param is updated here, but these are not updated in join->tmp_table_param.

            varun Varun Gupta (Inactive) added a comment - In the function JOIN::create_postjoin_aggr_table in sql_select.cc, the tmp_table_param field is not updated by the new values of the tab->tmp_table_param. TABLE* table= create_tmp_table(thd, tab->tmp_table_param, *table_fields, table_group, distinct, save_sum_fields, select_options, table_rows_limit, "" , true , keep_row_order); the tab->tmp_table_param is updated here, but these are not updated in join->tmp_table_param.

            Looking at the relevant code.

            There are two TMP_TABLE_PARAM objects:

            1. join->tmp_table_param
            2. join->join_tab[N]->tmp_table_param

            The first one seems to be used at optimization stage for storing various
            global parameters (like tmp_table_param.precomputed_group_by).

            The second one was introduced in 10.2. It is there to provide "new" handling
            for cases where the JOIN is executed using multiple temporary tables.

            (I dont fully understand the "old" way but it involved temporary "dummy"
            JOIN objects, etc. The new way is have JOIN_TABs for operations that write
            to temporary tables)

            So, looking at what JOIN::create_postjoin_aggr_table does.

            Copy JOIN::tmp_table_param into JOIN_TAB::tmp_table_param:

              tab->tmp_table_param= new TMP_TABLE_PARAM(tmp_table_param);
            

            Then, call create_tmp_table:

              TABLE* table= create_tmp_table(thd, tab->tmp_table_param, *table_fields,
                                             table_group, distinct,
                                             ...
            

            create_tmp_table fills certain members of TMP_TABLE_PARAM, e.g. recinfo.
            That is, tab->tmp_table_param has data describing the temporary table.

            Then, execution proceeds and eventually we reach JOIN::rollup_write_data
            It has this call:

            	if (create_internal_tmp_table_from_heap(thd, table_arg, 
                                                            tmp_table_param.start_recinfo,
                                                            &tmp_table_param.recinfo,
            

            Note that it uses JOIN::tmp_table_param, while the data describing the
            temptable is in join_tab->tmp_table_param.

            Going one frame up into end_write_group, I see:

                      int error= table->file->ha_write_tmp_row(table->record[0]);
                      if (error && 
                          create_internal_tmp_table_from_heap(join->thd, table,
                                                      join_tab->tmp_table_param->start_recinfo,
                                                      &join_tab->tmp_table_param->recinfo,
                                                               error, 0, NULL))
            	    DBUG_RETURN(NESTED_LOOP_ERROR);
                    }
                    if (join->rollup.state != ROLLUP::STATE_NONE)
            	{
            	  if (join->rollup_write_data((uint) (idx+1), table))
            	    DBUG_RETURN(NESTED_LOOP_ERROR);
            	}
            

            So I guess it's better if rollup_write_data used join_tab->tmp_table_param, just like create_internal_tmp_table_from_heap call above does.

            psergei Sergei Petrunia added a comment - Looking at the relevant code. There are two TMP_TABLE_PARAM objects: 1. join->tmp_table_param 2. join->join_tab [N] ->tmp_table_param The first one seems to be used at optimization stage for storing various global parameters (like tmp_table_param.precomputed_group_by). The second one was introduced in 10.2. It is there to provide "new" handling for cases where the JOIN is executed using multiple temporary tables. (I dont fully understand the "old" way but it involved temporary "dummy" JOIN objects, etc. The new way is have JOIN_TABs for operations that write to temporary tables) So, looking at what JOIN::create_postjoin_aggr_table does. Copy JOIN::tmp_table_param into JOIN_TAB::tmp_table_param: tab->tmp_table_param= new TMP_TABLE_PARAM(tmp_table_param); Then, call create_tmp_table: TABLE* table= create_tmp_table(thd, tab->tmp_table_param, *table_fields, table_group, distinct, ... create_tmp_table fills certain members of TMP_TABLE_PARAM, e.g. recinfo . That is, tab->tmp_table_param has data describing the temporary table. Then, execution proceeds and eventually we reach JOIN::rollup_write_data It has this call: if (create_internal_tmp_table_from_heap(thd, table_arg, tmp_table_param.start_recinfo, &tmp_table_param.recinfo, Note that it uses JOIN::tmp_table_param, while the data describing the temptable is in join_tab->tmp_table_param. Going one frame up into end_write_group, I see: int error= table->file->ha_write_tmp_row(table->record[0]); if (error && create_internal_tmp_table_from_heap(join->thd, table, join_tab->tmp_table_param->start_recinfo, &join_tab->tmp_table_param->recinfo, error, 0, NULL)) DBUG_RETURN(NESTED_LOOP_ERROR); } if (join->rollup.state != ROLLUP::STATE_NONE) { if (join->rollup_write_data((uint) (idx+1), table)) DBUG_RETURN(NESTED_LOOP_ERROR); } So I guess it's better if rollup_write_data used join_tab->tmp_table_param, just like create_internal_tmp_table_from_heap call above does.
            psergei Sergei Petrunia added a comment - Igor, please review. http://lists.askmonty.org/pipermail/commits/2017-January/010571.html
            igor Igor Babaev added a comment -

            The patch is approved. Ok to push.

            igor Igor Babaev added a comment - The patch is approved. Ok to push.
            igor Igor Babaev added a comment -

            Ok to push

            igor Igor Babaev added a comment - Ok to push

            People

              psergei Sergei Petrunia
              sbester1 sbester1
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

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