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

InnoDB: Assertion failure in row_merge_read_clustered_index upon ALTER on table with indexed virtual columns

Details

    Description

      --source include/have_innodb.inc
      --source include/have_sequence.inc
       
      CREATE TABLE t1 (
        id BIGINT AUTO_INCREMENT PRIMARY KEY,
        a INT,
        va INT ZEROFILL AS (a) VIRTUAL,
        b TIMESTAMP,
        c CHAR(204),
        vc CHAR(8),
        KEY(vc,c(64),b,va)
      ) ENGINE=InnoDB CHARACTER SET utf32;
      INSERT INTO t1 (id) SELECT NULL FROM seq_1_to_75;
      INSERT IGNORE INTO t1 (id, a) VALUES (NULL, -1);
      ALTER TABLE t1 FORCE;
       
      # CLeanup
      DROP TABLE t1;
      

      Run with --mysqld=--innodb-sort-buffer-size=64K

      10.3 b1b4d67b

      2021-06-08 02:36:35 0x7f3bf5354700  InnoDB: Assertion failure in file /data/src/10.3/storage/innobase/row/row0merge.cc line 2697
       
      #6  0x000055839690fa33 in ut_dbg_assertion_failed (expr=0x0, file=0x558396fc16f0 "/data/src/10.3/storage/innobase/row/row0merge.cc", line=2697) at /data/src/10.3/storage/innobase/ut/ut0dbg.cc:60
      #7  0x000055839680b6b8 in row_merge_read_clustered_index (trx=0x7f3bf5e520d0, table=0x7f3b9c0abb60, old_table=0x7f3b9c1901c0, new_table=0x7f3b9c0af1c0, online=false, index=0x7f3b9c0aeef0, fts_sort_idx=0x0, psort_info=0x0, files=0x7f3b9c033340, key_numbers=0x7f3b9c0aef00, n_index=2, defaults=0x0, add_v=0x0, col_map=0x7f3b9c0aef98, add_autoinc=18446744073709551615, sequence=..., block=0x7f3bf52da000 "\002\a`\276\255\203\200", skip_pk_sort=true, tmpfd=0x7f3bf53504e0, stage=0x7f3b9c1805d0, pct_cost=33.333333333333336, crypt_block=0x0, eval_table=0x7f3b9c0abb60, allow_not_null=false) at /data/src/10.3/storage/innobase/row/row0merge.cc:2697
      #8  0x0000558396812361 in row_merge_build_indexes (trx=0x7f3bf5e520d0, old_table=0x7f3b9c1901c0, new_table=0x7f3b9c0af1c0, online=false, indexes=0x7f3b9c0aeef0, key_numbers=0x7f3b9c0aef00, n_indexes=2, table=0x7f3b9c0abb60, defaults=0x0, col_map=0x7f3b9c0aef98, add_autoinc=18446744073709551615, sequence=..., skip_pk_sort=true, stage=0x7f3b9c1805d0, add_v=0x0, eval_table=0x7f3b9c0abb60, allow_not_null=false) at /data/src/10.3/storage/innobase/row/row0merge.cc:4721
      #9  0x00005583966ced27 in ha_innobase::inplace_alter_table (this=0x7f3b9c036398, altered_table=0x7f3b9c0abb60, ha_alter_info=0x7f3bf5351170) at /data/src/10.3/storage/innobase/handler/handler0alter.cc:7221
      #10 0x00005583962084d7 in handler::ha_inplace_alter_table (this=0x7f3b9c036398, altered_table=0x7f3b9c0abb60, ha_alter_info=0x7f3bf5351170) at /data/src/10.3/sql/handler.h:4212
      #11 0x00005583961fc782 in mysql_inplace_alter_table (thd=0x7f3b9c000d90, table_list=0x7f3b9c012bb8, table=0x7f3b9c0bbc10, altered_table=0x7f3b9c0abb60, ha_alter_info=0x7f3bf5351170, target_mdl_request=0x7f3bf53512f0, alter_ctx=0x7f3bf53518a0) at /data/src/10.3/sql/sql_table.cc:7744
      #12 0x000055839620353f in mysql_alter_table (thd=0x7f3b9c000d90, new_db=0x7f3b9c005488, new_name=0x7f3b9c005870, create_info=0x7f3bf5352490, table_list=0x7f3b9c012bb8, alter_info=0x7f3bf53523d0, order_num=0, order=0x0, ignore=false) at /data/src/10.3/sql/sql_table.cc:10049
      #13 0x0000558396294416 in Sql_cmd_alter_table::execute (this=0x7f3b9c013220, thd=0x7f3b9c000d90) at /data/src/10.3/sql/sql_alter.cc:512
      #14 0x000055839611dc3f in mysql_execute_command (thd=0x7f3b9c000d90) at /data/src/10.3/sql/sql_parse.cc:6075
      #15 0x00005583961232fe in mysql_parse (thd=0x7f3b9c000d90, rawbuf=0x7f3b9c012ae8 "ALTER TABLE t1 FORCE", length=20, parser_state=0x7f3bf5353530, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:7870
      #16 0x000055839610f9bb in dispatch_command (command=COM_QUERY, thd=0x7f3b9c000d90, packet=0x7f3b9c008f41 "ALTER TABLE t1 FORCE", packet_length=20, is_com_multi=false, is_next_command=false) at /data/src/10.3/sql/sql_parse.cc:1852
      #17 0x000055839610e35b in do_command (thd=0x7f3b9c000d90) at /data/src/10.3/sql/sql_parse.cc:1398
      #18 0x000055839628e2ac in do_handle_one_connection (connect=0x55839a0cd420) at /data/src/10.3/sql/sql_connect.cc:1403
      #19 0x000055839628e008 in handle_one_connection (arg=0x55839a0cd420) at /data/src/10.3/sql/sql_connect.cc:1308
      #20 0x0000558396c63f69 in pfs_spawn_thread (arg=0x55839a0b0260) at /data/src/10.3/storage/perfschema/pfs.cc:1869
      #21 0x00007f3bfc4a7609 in start_thread (arg=<optimized out>) at pthread_create.c:477
      #22 0x00007f3bfc3ce293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
      

      Reproducible on 10.3+, debug- and non-debug alike.

      Attachments

        Issue Links

          Activity

            InnoDB fails to check the error condition DB_COMPUTE_VALUE_FAILED in row_merge_read_clustered_index(). So the following
            patch could fix this issue.

            diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
            index 9e84f9db033..07ccb5fcfe4 100644
            --- a/storage/innobase/row/row0merge.cc
            +++ b/storage/innobase/row/row0merge.cc
            @@ -2692,6 +2692,12 @@ row_merge_read_clustered_index(
                                                            new_table, psort_info, row, ext,
                                                            &doc_id, conv_heap,
                                                            &err, &v_heap, eval_table, trx)))) {
            +
            +                                       if (err == DB_COMPUTE_VALUE_FAILED) {
            +                                               trx->error_key_num = i;
            +                                               goto func_exit;
            +                                       }
            +
                                                    /* An empty buffer should have enough
                                                    room for at least one record. */
                                                    ut_error;
            

            thiru Thirunarayanan Balathandayuthapani added a comment - - edited InnoDB fails to check the error condition DB_COMPUTE_VALUE_FAILED in row_merge_read_clustered_index() . So the following patch could fix this issue. diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 9e84f9db033..07ccb5fcfe4 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -2692,6 +2692,12 @@ row_merge_read_clustered_index( new_table, psort_info, row, ext, &doc_id, conv_heap, &err, &v_heap, eval_table, trx)))) { + + if (err == DB_COMPUTE_VALUE_FAILED) { + trx->error_key_num = i; + goto func_exit; + } + /* An empty buffer should have enough room for at least one record. */ ut_error;

            Would the following work? It should avoid a crash in a non-debug server for any errors here, and report the problematic index:

            diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
            index e3b3f2c2762..7d3693e8bbc 100644
            --- a/storage/innobase/row/row0merge.cc
            +++ b/storage/innobase/row/row0merge.cc
            @@ -2569,15 +2569,15 @@ row_merge_read_clustered_index(
             						&err, &v_heap, eval_table, trx)))) {
             					/* An empty buffer should have enough
             					room for at least one record. */
            -					ut_error;
            +					ut_ad(err == DB_COMPUTE_VALUE_FAILED);
            +				} else if (err == DB_SUCCESS) {
            +					file->n_rec += rows_added;
            +					continue;
             				}
             
            -				if (err != DB_SUCCESS) {
            +				trx->error_key_num = i;
             				break;
             			}
            -
            -				file->n_rec += rows_added;
            -			}
             		}
             
             		if (row == NULL) {
            
            

            I think that this variant would require stress testing.

            marko Marko Mäkelä added a comment - Would the following work? It should avoid a crash in a non-debug server for any errors here, and report the problematic index: diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index e3b3f2c2762..7d3693e8bbc 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -2569,15 +2569,15 @@ row_merge_read_clustered_index( &err, &v_heap, eval_table, trx)))) { /* An empty buffer should have enough room for at least one record. */ - ut_error; + ut_ad(err == DB_COMPUTE_VALUE_FAILED); + } else if (err == DB_SUCCESS) { + file->n_rec += rows_added; + continue; } - if (err != DB_SUCCESS) { + trx->error_key_num = i; break; } - - file->n_rec += rows_added; - } } if (row == NULL) { I think that this variant would require stress testing.

            People

              thiru Thirunarayanan Balathandayuthapani
              elenst Elena Stepanova
              Votes:
              0 Vote for this issue
              Watchers:
              3 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.