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

InnoDB fails to purge secondary index records when indexed virtual columns exist

    XMLWordPrintable

Details

    Description

      When I tested MDEV-24402 CHECK TABLE...EXTENDED, the test gcol.innodb_virtual_purge would fail because secondary indexes contain orphan records. Here is a reduced test case:

      --source include/have_innodb.inc
       
      CREATE TABLE t1 (a INT, b INT, a1 INT AS(a) VIRTUAL,
      INDEX(a1),INDEX(b)) ENGINE=InnoDB;
      INSERT INTO t1 SET a=1, b=1;
       
      UPDATE t1 SET a=2, b=3;
      let $datadir=`select @@datadir`;
      let $sec=`select 3*@@innodb_page_size`;
       
      SET GLOBAL innodb_fast_shutdown=0;
      --source include/shutdown_mysqld.inc
      --exec od -Ax -t x1 -j $sec $datadir/test/t1.ibd
      --source include/start_mysqld.inc
      DROP TABLE t1;
      

      According to the od output, all history for the clustered index record (data fields starting at 0xc07e = 0xc063+0x001b) was purged. The fields are (DB_ROW_ID,DB_TRX_ID,DB_ROLL_PTR,a,b)=(0x200,0,1<<55,2,3):

      10.3 ce23802c0e4c85018f2141d2ebb0602dc0d3d6d8

      00c060 02 00 1b 69 6e 66 69 6d 75 6d 00 02 00 0b 00 00
      00c070 73 75 70 72 65 6d 75 6d 00 00 00 10 ff f2 00 00
      00c080 00 00 02 00 00 00 00 00 00 00 80 00 00 00 00 00
      00c090 00 80 00 00 02 80 00 00 03 00 00 00 00 00 00 00
      

      In the secondary indexes, the delete-marked records created by the UPDATE were not purged. Here is the entry for index(a1):

      10.3 ce23802c0e4c85018f2141d2ebb0602dc0d3d6d8

      010060 02 00 1b 69 6e 66 69 6d 75 6d 00 03 00 0b 00 00
      010070 73 75 70 72 65 6d 75 6d 00 20 00 10 00 10 80 00
      010080 00 01 00 00 00 00 02 00 00 00 00 18 ff e2 80 00
      010090 00 02 00 00 00 00 02 00 00 00 00 00 00 00 00 00
      

      We see both the delete-marked (a,DB_ROW_ID)=(1,0x200) at 0x1007e as well as the correct record (a,DB_ROW_ID)=2,0x200) at 0x1008e. There is a garbage record in index(b) as well:

      10.3 ce23802c0e4c85018f2141d2ebb0602dc0d3d6d8

      014060 02 00 1b 69 6e 66 69 6d 75 6d 00 03 00 0b 00 00
      014070 73 75 70 72 65 6d 75 6d 00 20 00 10 00 10 80 00
      014080 00 01 00 00 00 00 02 00 00 00 00 18 ff e2 80 00
      014090 00 03 00 00 00 00 02 00 00 00 00 00 00 00 00 00
      

      The delete-marked (b,DB_ROW_ID)=(1,0x200) at 0x1e07e should have been purged. Only the record (b,DB_ROW_ID)=(3,0x200) should be there.

      I tracked this down to the following code in the function row_purge_upd_exist_or_extern_func():

      		if (row_upd_changes_ord_field_binary(node->index, node->update,
      						     thr, NULL, NULL)) {
      			/* Build the older version of the index entry */
      			dtuple_t*	entry = row_build_index_entry_low(
      				node->row, NULL, node->index,
      				heap, ROW_BUILD_FOR_PURGE);
      			row_purge_remove_sec_if_poss(node, node->index, entry);
      

      We end up with entry=nullptr for both indexes, because node->row is invalid or being accessed incorrectly. The pointer to data_error indicates a column that has not been fully initialized:

      10.3 ce23802c0e4c85018f2141d2ebb0602dc0d3d6d8

      Thread 22 hit Breakpoint 2, row_purge_remove_sec_if_poss (node=node@entry=0x5613c42f37a0, index=0x7f8414167a50, entry=0x0) at /mariadb/10.3/storage/innobase/row/row0purge.cc:688
      688		if (!entry) {
      1: node.table.name = {m_name = 0x7f8414158690 "test/t1"}
      (rr) p *node.row
      $1 = {info_bits = 0, n_fields = 5, n_fields_cmp = 5, fields = 0x7f841c009270, 
        n_v_fields = 1, v_fields = 0x7f841c0092e8, magic_n = 65478679}
      (rr) p *node.row.fields@5
      $2 = {{data = 0x5613c42f3d5d, ext = 0, spatial_status = 0, len = 4, type = {
            prtype = 1027, mtype = 6, len = 4, mbminlen = 0, mbmaxlen = 0}}, {
          data = 0x5613c42f3d63, ext = 0, spatial_status = 0, len = 4, type = {
            prtype = 1027, mtype = 6, len = 4, mbminlen = 0, mbmaxlen = 0}}, {
          data = 0x5613c3518908 <data_error>, ext = 0, spatial_status = 0, 
          len = 4294967295, type = {prtype = 111, mtype = 0, len = 0, mbminlen = 0, 
            mbmaxlen = 0}}, {data = 0x7f841c009210, ext = 0, spatial_status = 0, 
          len = 6, type = {prtype = 257, mtype = 8, len = 6, mbminlen = 0, 
            mbmaxlen = 0}}, {data = 0x7f841c009218, ext = 0, spatial_status = 0, 
          len = 7, type = {prtype = 258, mtype = 8, len = 7, mbminlen = 0, 
            mbmaxlen = 0}}}
      

      Attachments

        Issue Links

          Activity

            People

              marko Marko Mäkelä
              marko Marko Mäkelä
              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.