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

Race condition between DML and DDL when virtual and foreign key is involved

    XMLWordPrintable

Details

    Description

      InnoDB DDL reloads the table if there is any virtual column involved. At the same, concurrent
      dml access the DDL table (when fk is involved) and access the freed table.

      Below test case to repeat the issue:

      --source include/have_innodb.inc
      CREATE TABLE t1(f1 int not null, f2 int as(f1) virtual,
                      primary key(f1))engine=innodb;
      CREATE TABLE t2(f1 INT NOT NULL, primary key(f1),
                      foreign key(f1) references t1(f1) on update cascade)engine=innodb;
      INSERT into t1(f1) values(1), (2);
      INSERT INTO t2 values(1);
      SET DEBUG_SYNC="innodb_row_ins_step_enter SIGNAL con1_start WAIT_FOR con1_alter_commit";
      SET DEBUG_SYNC="row_ins_foreign_constraint_wait SIGNAL default_insert WAIT_FOR alter_finish";
      SEND INSERT INTO t2 VALUES(2);
       
      connect(con1,localhost,root,,,);
      SET DEBUG_SYNC="now WAIT_FOR con1_start";
      SET DEBUG_SYNC="commit_cache_before_change SIGNAL con1_alter_commit WAIT_FOR default_insert";
      ALTER TABLE t1 ADD INDEX(f2);
      SET DEBUG_SYNC="now SIGNAL alter_finish";
       
      connection default;
      reap;
      disconnect con1;
      SHOW CREATE TABLE t1;
      DROP TABLE t2, t1;
      

      Patch to add debug sync points:

      diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
      index 6a8986d76d2..93c090f2127 100644
      --- a/storage/innobase/handler/handler0alter.cc
      +++ b/storage/innobase/handler/handler0alter.cc
      @@ -11441,6 +11441,7 @@ ha_innobase::commit_inplace_alter_table(
              purge_sys.stop_SYS();
              trx->commit(deleted);
       
      +       DEBUG_SYNC_C("commit_cache_before_change");
              /* At this point, the changes to the persistent storage have
              been committed or rolled back. What remains to be done is to
              update the in-memory structures, close some handles, release
      diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
      index a4471104543..c9b696fe448 100644
      --- a/storage/innobase/row/row0ins.cc
      +++ b/storage/innobase/row/row0ins.cc
      @@ -1615,6 +1615,7 @@ row_ins_check_foreign_constraint(
                      goto exit_func;
              }
       
      +       DEBUG_SYNC_C("row_ins_foreign_constraint_wait");
              mtr_start(&mtr);
       
              /* Store old value on n_fields_cmp */
      

      Stack trace:

      #5  0x00007ffff782871b in __assert_fail_base (fmt=0x7ffff79dd150 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", 
          assertion=0x555557236df0 "!index()->is_ibuf() || ibuf_inside(mtr)", file=0x555557236760 "/home/thiru/mariadb_parent/server/10.6/storage/innobase/btr/btr0cur.cc", 
          line=939, function=<optimized out>) at ./assert/assert.c:92
      #6  0x00007ffff7839e96 in __GI___assert_fail (assertion=0x555557236df0 "!index()->is_ibuf() || ibuf_inside(mtr)", 
          file=0x555557236760 "/home/thiru/mariadb_parent/server/10.6/storage/innobase/btr/btr0cur.cc", line=939, 
          function=0x555557236d90 "dberr_t btr_cur_t::search_leaf(const dtuple_t*, page_cur_mode_t, btr_latch_mode, mtr_t*)") at ./assert/assert.c:101
      #7  0x0000555556a0505a in btr_cur_t::search_leaf (this=0x7ffff15b1b10, tuple=0x7fffb8203498, mode=PAGE_CUR_GE, latch_mode=BTR_SEARCH_LEAF, mtr=0x7ffff15b1e90)
          at /home/thiru/mariadb_parent/server/10.6/storage/innobase/btr/btr0cur.cc:939
      #8  0x0000555556757c46 in btr_pcur_open (tuple=0x7fffb8203498, mode=PAGE_CUR_GE, latch_mode=BTR_SEARCH_LEAF, cursor=0x7ffff15b1b10, mtr=0x7ffff15b1e90)
          at /home/thiru/mariadb_parent/server/10.6/storage/innobase/include/btr0pcur.h:431
      #9  0x00005555568e1ec3 in row_ins_check_foreign_constraint (check_ref=1, foreign=0x7fffb820cb58, table=0x7fffb8043328, entry=0x7fffb8203498, thr=0x7fffb8065fe8)
          at /home/thiru/mariadb_parent/server/10.6/storage/innobase/row/row0ins.cc:1628
      #10 0x00005555568e2aa6 in row_ins_check_foreign_constraints (table=0x7fffb8043328, index=0x7fffb8230388, pk=true, entry=0x7fffb8203498, thr=0x7fffb8065fe8)
          at /home/thiru/mariadb_parent/server/10.6/storage/innobase/row/row0ins.cc:1953
      #11 0x00005555568e7205 in row_ins_clust_index_entry (index=0x7fffb8230388, entry=0x7fffb8203498, thr=0x7fffb8065fe8, n_ext=0)
          at /home/thiru/mariadb_parent/server/10.6/storage/innobase/row/row0ins.cc:3229
      #12 0x00005555568e790e in row_ins_index_entry (index=0x7fffb8230388, entry=0x7fffb8203498, thr=0x7fffb8065fe8)
          at /home/thiru/mariadb_parent/server/10.6/storage/innobase/row/row0ins.cc:3399
      #13 0x00005555568e8264 in row_ins_index_entry_step (node=0x7fffb8065dd0, thr=0x7fffb8065fe8) at /home/thiru/mariadb_parent/server/10.6/storage/innobase/row/row0ins.cc:3567
      #14 0x00005555568e8786 in row_ins (node=0x7fffb8065dd0, thr=0x7fffb8065fe8) at /home/thiru/mariadb_parent/server/10.6/storage/innobase/row/row0ins.cc:3692
      #15 0x00005555568e8f73 in row_ins_step (thr=0x7fffb8065fe8) at /home/thiru/mariadb_parent/server/10.6/storage/innobase/row/row0ins.cc:3821
      #16 0x000055555690b407 in row_insert_for_mysql (mysql_rec=0x7fffb8064c38 "\377\002", prebuilt=0x7fffb8065908, ins_mode=ROW_INS_NORMAL)
          at /home/thiru/mariadb_parent/server/10.6/storage/innobase/row/row0mysql.cc:1308
      #17 0x0000555556731861 in ha_innobase::write_row (this=0x7fffb80650a0, record=0x7fffb8064c38 "\377\002")
          at /home/thiru/mariadb_parent/server/10.6/storage/innobase/handler/ha_innodb.cc:7904
      #18 0x00005555562bd36a in handler::ha_write_row (this=0x7fffb80650a0, buf=0x7fffb8064c38 "\377\002") at /home/thiru/mariadb_parent/server/10.6/sql/handler.cc:7614
      #19 0x0000555555e9dcdf in write_record (thd=0x7fffb8000dc8, table=0x7fffb8064788, info=0x7ffff15b2a60, sink=0x0)
          at /home/thiru/mariadb_parent/server/10.6/sql/sql_insert.cc:2156
      #20 0x0000555555e9a7f1 in mysql_insert (thd=0x7fffb8000dc8, table_list=0x7fffb8015728, fields=..., values_list=..., update_fields=..., update_values=..., duplic=DUP_ERROR, 
          ignore=false, result=0x0) at /home/thiru/mariadb_parent/server/10.6/sql/sql_insert.cc:1128
      #21 0x0000555555ef1c4d in mysql_execute_command (thd=0x7fffb8000dc8, is_called_from_prepared_stmt=false) at /home/thiru/mariadb_parent/server/10.6/sql/sql_parse.cc:4570
      #22 0x0000555555efd978 in mysql_parse (thd=0x7fffb8000dc8, rawbuf=0x7fffb8015650 "INSERT INTO t2 VALUES(2)", length=24, parser_state=0x7ffff15b3300)
          at /home/thiru/mariadb_parent/server/10.6/sql/sql_parse.cc:8021
      #23 0x0000555555ee97ea in dispatch_command (command=COM_QUERY, thd=0x7fffb8000dc8, packet=0x7fffb800b8e9 "INSERT INTO t2 VALUES(2)", packet_length=24, blocking=true)
          at /home/thiru/mariadb_parent/server/10.6/sql/sql_parse.cc:1896
      

      Demostrated the above test case with the help of rr trace:

      AddressSanitizer: heap-use-after-free /data/Server/bb-10.6-MDEV-29545/storage/innobase/page/page0cur.cc:733 in page_cur_search_with_match_bytes(dtuple_t const*, page_cur_mode_t, unsigned long*, unsigned long*, unsigned long*, unsigned long*, page_cur_t*)
      sdp:/data1/results/1679487659/TBR-1855$ _RR_TRACE_DIR=./1/rr rr replay --mark-stdio
      

      Attachments

        Activity

          People

            nikitamalyavin Nikita Malyavin
            thiru Thirunarayanan Balathandayuthapani
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Git Integration

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