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

Server crashes in dict_table_t::instant_column upon ADD COLUMN

Details

    Description

      Attention: It only fails for me on a NON-DEBUG build. Neither debug, nor ASAN, nor valgrind show any obvious errors.

      --source include/have_innodb.inc
       
      CREATE TABLE tx (pk INT PRIMARY KEY) ENGINE=InnoDB;
      CREATE TABLE t1 (pk INT, a INT, PRIMARY KEY (pk), KEY (a), FOREIGN KEY (a) REFERENCES tx (pk)) ENGINE=InnoDB;
       
      SET FOREIGN_KEY_CHECKS=OFF;
       
      --error ER_FK_COLUMN_CANNOT_DROP
      ALTER TABLE t1 DROP a;
       
      SET FOREIGN_KEY_CHECKS=ON;
       
      ALTER TABLE t1 ADD b INT;
      --error ER_DROP_INDEX_FK
      ALTER TABLE t1 DROP a;
      ALTER TABLE t1 ADD c INT;
       
      # Cleanup
      DROP TABLE t1, tx;
      

      10.4 RelWithDebInfo b1034099

      #2  <signal handler called>
      #3  0x000056099d648ce1 in dict_table_t::instant_column (this=<optimized out>, table=..., col_map=<optimized out>) at /data/src/10.4/storage/innobase/handler/handler0alter.cc:694
      #4  0x000056099d1207c9 in instant_column (this=0x7f65e8013c08) at /data/src/10.4/storage/innobase/handler/handler0alter.cc:1082
      #5  innobase_instant_try (ha_alter_info=ha_alter_info@entry=0x7f6640bd4e10, ctx=ctx@entry=0x7f65e8013c08, trx=trx@entry=0x7f66416a1158, table=<optimized out>, altered_table=<optimized out>, altered_table=<optimized out>) at /data/src/10.4/storage/innobase/handler/handler0alter.cc:5508
      #6  0x000056099d64572b in commit_try_norebuild (table_name=0x7f65e8082aad "t1", trx=0x7f66416a1158, old_table=<optimized out>, altered_table=<optimized out>, ctx=0x7f65e8013c08, ha_alter_info=<optimized out>) at /data/src/10.4/storage/innobase/handler/handler0alter.cc:10155
      #7  ha_innobase::commit_inplace_alter_table (this=<optimized out>, altered_table=<optimized out>, ha_alter_info=<optimized out>, commit=<optimized out>) at /data/src/10.4/storage/innobase/handler/handler0alter.cc:10824
      #8  0x000056099d11b6c2 in mysql_inplace_alter_table (thd=thd@entry=0x7f65e80009a8, table_list=0x7f65e8011f80, table=table@entry=0x7f65e80ccb28, altered_table=altered_table@entry=0x7f65e803f1a8, ha_alter_info=ha_alter_info@entry=0x7f6640bd4e10, inplace_supported=inplace_supported@entry=HA_ALTER_INPLACE_INSTANT, alter_ctx=0x7f6640bd5660, target_mdl_request=0x7f6640bd4eb0) at /data/src/10.4/sql/sql_table.cc:7695
      #9  0x000056099d2a6f2b in mysql_alter_table (thd=<optimized out>, new_db=<optimized out>, new_name=<optimized out>, create_info=<optimized out>, table_list=0x7f65e8011f80, alter_info=0x7f6640bd6160, order_num=0, order=0x0, ignore=false) at /data/src/10.4/sql/sql_table.cc:9922
      #10 0x000056099d2f515b in Sql_cmd_alter_table::execute (this=0x1fd97a02082, thd=0x7f65e80009a8) at /data/src/10.4/sql/sql_alter.cc:499
      #11 0x000056099d20ce56 in mysql_execute_command (thd=thd@entry=0x7f65e80009a8) at /data/src/10.4/sql/sql_parse.cc:6346
      #12 0x000056099d214311 in mysql_parse (thd=thd@entry=0x7f65e80009a8, rawbuf=<optimized out>, length=24, parser_state=parser_state@entry=0x7f6640bd91d0, is_com_multi=is_com_multi@entry=false, is_next_command=is_next_command@entry=false) at /data/src/10.4/sql/sql_parse.cc:8157
      #13 0x000056099d216b3f in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x7f65e80009a8, packet=packet@entry=0x7f65e8009b39 "ALTER TABLE t1 ADD c INT", packet_length=packet_length@entry=24, is_com_multi=is_com_multi@entry=false, is_next_command=is_next_command@entry=false) at /data/src/10.4/sql/sql_parse.cc:1829
      #14 0x000056099d217f97 in do_command (thd=0x7f65e80009a8) at /data/src/10.4/sql/sql_parse.cc:1358
      #15 0x000056099d2f252c in do_handle_one_connection (connect=connect@entry=0x5609a05dd588) at /data/src/10.4/sql/sql_connect.cc:1399
      #16 0x000056099d2f2694 in handle_one_connection (arg=arg@entry=0x5609a05dd588) at /data/src/10.4/sql/sql_connect.cc:1302
      #17 0x000056099d60ff44 in pfs_spawn_thread (arg=0x5609a05dd5e8) at /data/src/10.4/storage/perfschema/pfs.cc:1862
      #18 0x00007f6649569494 in start_thread (arg=0x7f6640bda700) at pthread_create.c:333
      #19 0x00007f664794f93f in clone () from /lib/x86_64-linux-gnu/libc.so.6
      

      Not reproducible on 10.3.

      Attachments

        Issue Links

          Activity

            Additional note.
            If the same test case is run on a build with DBUG_ASSERT_AS_PRINTF, it prints an extra assertion failure before the crash. I'm not getting this assertion failure on debug builds, either.

            Warning: assertion failed: f.col->is_virtual() at /data/src/10.4/storage/innobase/handler/handler0alter.cc line 690
            Attempting backtrace to find out the reason for the assert:
            stack_bottom = 0x0 thread_stack 0x49000
            mysys/stacktrace.c:270(my_print_stacktrace)[0x55ab7bf9ae09]
            handler/handler0alter.cc:690(dict_table_t::instant_column(dict_table_t const&, unsigned long const*))[0x55ab7bcf75dc]
            handler/handler0alter.cc:1082(ha_innobase_inplace_ctx::instant_column())[0x55ab7b76ed62]
            handler/handler0alter.cc:10155(commit_try_norebuild)[0x55ab7bcf32af]
            sql/sql_table.cc:7695(mysql_inplace_alter_table(THD*, TABLE_LIST*, TABLE*, TABLE*, Alter_inplace_info*, enum_alter_inplace_r
            esult, MDL_request*, Alter_table_ctx*) [clone .isra.168])[0x55ab7b76915c]
            sql/sql_table.cc:9922(mysql_alter_table(THD*, st_mysql_const_lex_string const*, st_mysql_const_lex_string const*, HA_CREATE_
            INFO*, TABLE_LIST*, Alter_info*, unsigned int, st_order*, bool))[0x55ab7b905d49]
            sql/sql_alter.cc:499(Sql_cmd_alter_table::execute(THD*))[0x55ab7b959da2]
            sql/sql_parse.cc:6346(mysql_execute_command(THD*))[0x55ab7b868bcf]
            sql/sql_parse.cc:8174(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x55ab7b8709b0]
            sql/sql_parse.cc:1893(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x55ab7b873655]
            sql/sql_parse.cc:1359(do_command(THD*))[0x55ab7b874732]
            sql/sql_connect.cc:1399(do_handle_one_connection(CONNECT*))[0x55ab7b956e6c]
            sql/sql_connect.cc:1304(handle_one_connection)[0x55ab7b956fd4]
            perfschema/pfs.cc:1865(pfs_spawn_thread)[0x55ab7bcb7c84]
            nptl/pthread_create.c:333(start_thread)[0x7fc265eba494]
            x86_64/clone.S:99(clone)[0x7fc2642a093f]
            190301  0:05:59 [ERROR] mysqld got signal 11 ;
            

            elenst Elena Stepanova added a comment - Additional note. If the same test case is run on a build with DBUG_ASSERT_AS_PRINTF , it prints an extra assertion failure before the crash. I'm not getting this assertion failure on debug builds, either. Warning: assertion failed: f.col->is_virtual() at /data/src/10.4/storage/innobase/handler/handler0alter.cc line 690 Attempting backtrace to find out the reason for the assert: stack_bottom = 0x0 thread_stack 0x49000 mysys/stacktrace.c:270(my_print_stacktrace)[0x55ab7bf9ae09] handler/handler0alter.cc:690(dict_table_t::instant_column(dict_table_t const&, unsigned long const*))[0x55ab7bcf75dc] handler/handler0alter.cc:1082(ha_innobase_inplace_ctx::instant_column())[0x55ab7b76ed62] handler/handler0alter.cc:10155(commit_try_norebuild)[0x55ab7bcf32af] sql/sql_table.cc:7695(mysql_inplace_alter_table(THD*, TABLE_LIST*, TABLE*, TABLE*, Alter_inplace_info*, enum_alter_inplace_r esult, MDL_request*, Alter_table_ctx*) [clone .isra.168])[0x55ab7b76915c] sql/sql_table.cc:9922(mysql_alter_table(THD*, st_mysql_const_lex_string const*, st_mysql_const_lex_string const*, HA_CREATE_ INFO*, TABLE_LIST*, Alter_info*, unsigned int, st_order*, bool))[0x55ab7b905d49] sql/sql_alter.cc:499(Sql_cmd_alter_table::execute(THD*))[0x55ab7b959da2] sql/sql_parse.cc:6346(mysql_execute_command(THD*))[0x55ab7b868bcf] sql/sql_parse.cc:8174(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x55ab7b8709b0] sql/sql_parse.cc:1893(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x55ab7b873655] sql/sql_parse.cc:1359(do_command(THD*))[0x55ab7b874732] sql/sql_connect.cc:1399(do_handle_one_connection(CONNECT*))[0x55ab7b956e6c] sql/sql_connect.cc:1304(handle_one_connection)[0x55ab7b956fd4] perfschema/pfs.cc:1865(pfs_spawn_thread)[0x55ab7bcb7c84] nptl/pthread_create.c:333(start_thread)[0x7fc265eba494] x86_64/clone.S:99(clone)[0x7fc2642a093f] 190301 0:05:59 [ERROR] mysqld got signal 11 ;

            The table metadata must have been corrupted before the failing ALTER TABLE. The index->fields[].col for index a are wrong. I suspect a bug in dict_table_t::rollback_instant().

            marko Marko Mäkelä added a comment - The table metadata must have been corrupted before the failing ALTER TABLE . The index->fields[].col for index a are wrong. I suspect a bug in dict_table_t::rollback_instant() .

            I intend to push the following fix, along with the test case, once I have tested this on 10.2:

            Author: Marko Mäkelä
            Date:   Fri Mar 1 10:16:56 2019 +0200
             
                MDEV-18775 Fix ALTER TABLE error handling for DROP INDEX
                
                On an error (such as when an index cannot be dropped due to
                FOREIGN KEY constraints), the field dict_index_t::to_be_dropped
                was only being cleared in debug builds, even though the field
                is available and being used also in non-debug builds.
                
                This was a regression that was introduced by myself originally
                in MySQL 5.7.6 and later merged to MariaDB 10.2.2, in
                https://github.com/mysql/mysql-server/commit/d39898de8e0de21f64ce94cd4ea698675edfb447
                
                An error manifested itself in the MariaDB Server 10.4 non-debug build,
                involving instant ADD or DROP column. Because an earlier failed
                ALTER TABLE operation incorrectly left the dict_index_t::to_be_dropped
                flag set, the column pointers of the index fields would fail to be
                adjusted for instant ADD or DROP column (MDEV-15562). The instant
                ADD COLUMN in MariaDB Server 10.3 is unlikely to be affected by a
                similar scenario, because dict_table_t::instant_add_column() in 10.3
                is applying the transformations to all indexes, not skipping
                to-be-dropped ones.
             
            diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
            index 47cc31ce9dc..c04c69ba8e2 100644
            --- a/storage/innobase/handler/handler0alter.cc
            +++ b/storage/innobase/handler/handler0alter.cc
            @@ -5142,14 +5142,12 @@ prepare_inplace_alter_table_dict(
             	ut_ad(!user_table->drop_aborted);
             
             err_exit:
            -#ifdef UNIV_DEBUG
             	/* Clear the to_be_dropped flag in the data dictionary cache. */
             	for (ulint i = 0; i < ctx->num_to_drop_index; i++) {
             		DBUG_ASSERT(ctx->drop_index[i]->is_committed());
             		DBUG_ASSERT(ctx->drop_index[i]->to_be_dropped);
             		ctx->drop_index[i]->to_be_dropped = 0;
             	}
            -#endif /* UNIV_DEBUG */
             
             	row_mysql_unlock_data_dictionary(ctx->trx);
             
            

            marko Marko Mäkelä added a comment - I intend to push the following fix, along with the test case, once I have tested this on 10.2: Author: Marko Mäkelä Date: Fri Mar 1 10:16:56 2019 +0200   MDEV-18775 Fix ALTER TABLE error handling for DROP INDEX On an error (such as when an index cannot be dropped due to FOREIGN KEY constraints), the field dict_index_t::to_be_dropped was only being cleared in debug builds, even though the field is available and being used also in non-debug builds. This was a regression that was introduced by myself originally in MySQL 5.7.6 and later merged to MariaDB 10.2.2, in https://github.com/mysql/mysql-server/commit/d39898de8e0de21f64ce94cd4ea698675edfb447 An error manifested itself in the MariaDB Server 10.4 non-debug build, involving instant ADD or DROP column. Because an earlier failed ALTER TABLE operation incorrectly left the dict_index_t::to_be_dropped flag set, the column pointers of the index fields would fail to be adjusted for instant ADD or DROP column (MDEV-15562). The instant ADD COLUMN in MariaDB Server 10.3 is unlikely to be affected by a similar scenario, because dict_table_t::instant_add_column() in 10.3 is applying the transformations to all indexes, not skipping to-be-dropped ones.   diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 47cc31ce9dc..c04c69ba8e2 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -5142,14 +5142,12 @@ prepare_inplace_alter_table_dict( ut_ad(!user_table->drop_aborted); err_exit: -#ifdef UNIV_DEBUG /* Clear the to_be_dropped flag in the data dictionary cache. */ for (ulint i = 0; i < ctx->num_to_drop_index; i++) { DBUG_ASSERT(ctx->drop_index[i]->is_committed()); DBUG_ASSERT(ctx->drop_index[i]->to_be_dropped); ctx->drop_index[i]->to_be_dropped = 0; } -#endif /* UNIV_DEBUG */ row_mysql_unlock_data_dictionary(ctx->trx);

            People

              marko Marko Mäkelä
              elenst Elena Stepanova
              Votes:
              0 Vote for this issue
              Watchers:
              2 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.