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

Virtual column value not available during purge

    Details

      Description

      With the following patch applied, the test gcol.innodb_virtual_debug_purge would crash in purge:

      diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc
      index ad4991fb4e9..80513f7223e 100644
      --- a/storage/innobase/row/row0row.cc
      +++ b/storage/innobase/row/row0row.cc
      @@ -127,6 +127,7 @@ row_build_index_entry_low(
       
       			ut_ad(dfield_is_null(dfield2) ||
       			      dfield_get_len(dfield2) == 0 || dfield2->data);
      +			ut_ad(dfield2->type.mtype != DATA_MISSING);
       		} else {
       			dfield2 = dtuple_get_nth_field(row, col_no);
       			ut_ad(dfield_get_type(dfield2)->mtype == DATA_MISSING
      

      10.2 af6077b5358198384eb873ce26f88e7a7ecfe106

      #8  0x000056493cb05ca4 in row_build_index_entry_low (row=0x7fb5c400aa00, 
          ext=0x0, index=0x7fb598040a58, heap=0x7fb5c4008890, flag=1)
          at /mariadb/10.2/storage/innobase/row/row0row.cc:130
      #9  0x000056493caffbbc in row_purge_del_mark (node=0x56493ed4d0f8)
          at /mariadb/10.2/storage/innobase/row/row0purge.cc:788
      #10 0x000056493cb00826 in row_purge_record_func (node=0x56493ed4d0f8, 
          undo_rec=0x56493ed4d6a8 "", thr=0x56493ed4cf40, updated_extern=false)
          at /mariadb/10.2/storage/innobase/row/row0purge.cc:1102
      Thread 11 (Thread 0x7fb5ebfff700 (LWP 29131)):
      #6  0x000056493c56a7e2 in debug_sync (thd=0x7fb598000cf8, 
          sync_point_name=0x56493d0bf389 "inplace_after_index_build", name_len=25)
          at /mariadb/10.2/sql/debug_sync.cc:1552
      #7  0x000056493c9e1ede in ha_innobase::inplace_alter_table (
          this=0x7fb59807ffb0, altered_table=0x7fb5980f41e8, 
          ha_alter_info=0x7fb5ebffb5a0)
          at /mariadb/10.2/storage/innobase/handler/handler0alter.cc:6532
      #8  0x000056493c61089d in handler::ha_inplace_alter_table (this=
          0x7fb59807ffb0, altered_table=0x7fb5980f41e8, 
          ha_alter_info=0x7fb5ebffb5a0) at /mariadb/10.2/sql/handler.h:3783
      #9  0x000056493c6071a7 in mysql_inplace_alter_table (thd=0x7fb598000cf8, 
          table_list=0x7fb598011838, table=0x7fb598059668, 
          altered_table=0x7fb5980f41e8, ha_alter_info=0x7fb5ebffb5a0, 
          inplace_supported=HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE, 
          target_mdl_request=0x7fb5ebffb610, alter_ctx=0x7fb5ebffc1d0)
          at /mariadb/10.2/sql/sql_table.cc:7365
      #10 0x000056493c60c7c8 in mysql_alter_table (thd=0x7fb598000cf8, 
          new_db=0x7fb598011e48 "test", new_name=0x0, create_info=0x7fb5ebffcdf0, 
          table_list=0x7fb598011838, alter_info=0x7fb5ebffcd40, order_num=0, 
          order=0x0, ignore=false) at /mariadb/10.2/sql/sql_table.cc:9390
      #11 0x000056493c6844f7 in Sql_cmd_alter_table::execute (this=0x7fb598011f28, 
          thd=0x7fb598000cf8) at /mariadb/10.2/sql/sql_alter.cc:323
      #12 0x000056493c542078 in mysql_execute_command (thd=0x7fb598000cf8)
          at /mariadb/10.2/sql/sql_parse.cc:6225
      #13 0x000056493c54709e in mysql_parse (thd=0x7fb598000cf8, 
          rawbuf=0x7fb598011710 "ALTER TABLE t1 ADD INDEX idx (c), ALGORITHM=INPLACE, LOCK=NONE", length=62, parser_state=0x7fb5ebffe1b0, is_com_multi=false, 
          is_next_command=false) at /mariadb/10.2/sql/sql_parse.cc:8011
      

      This seems related to a MySQL 5.7 bug fix that worked around a similar issue by introducing the function row_purge_skip_uncommitted_virtual_index(). In this case, the ALTER TABLE has already completed the index creation inside InnoDB, but the metadata change has not been committed. The following assertion appears to be valid:

      diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc
      index ad4991fb4e9..3f4308d4bed 100644
      --- a/storage/innobase/row/row0row.cc
      +++ b/storage/innobase/row/row0row.cc
      @@ -127,6 +127,8 @@ row_build_index_entry_low(
       
       			ut_ad(dfield_is_null(dfield2) ||
       			      dfield_get_len(dfield2) == 0 || dfield2->data);
      +			ut_ad(dfield2->type.mtype != DATA_MISSING
      +			      || !index->is_committed());
       		} else {
       			dfield2 = dtuple_get_nth_field(row, col_no);
       			ut_ad(dfield_get_type(dfield2)->mtype == DATA_MISSING
      

      As noted in MDEV-11657, a better approach would be to write each key to the undo log record explicitly. Then purge and rollback should avoid evaluating any virtual columns.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                thiru Thirunarayanan Balathandayuthapani
                Reporter:
                marko Marko Mäkelä
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated: