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

FOREIGN KEY…SET NULL corrupts an index on a virtual column

Details

    Description

      MySQL 5.7.36 includes a bug fix with a test case:
      Bug #33053297 VIRTUAL INDEX CORRUPTED DURING CASCADE UPDATE ON CHILD TABLE
      The test case resembles MDEV-24041. A quick attempt to apply the patch (with some rewriting in row_ins_foreign_fill_virtual()) did not affect the outcome. There is a result difference:

      @@ -918,7 +918,6 @@
       1	NULL	2020-10-22 13:32:41	2020- 
       SELECT `date_sent` FROM `email_stats` WHERE `generated_sent_email` = '2020-';
       date_sent
      -2020-10-22 13:32:41
       DROP TABLE `email_stats`;
       DROP TABLE `emails`;
       # test-case 4
      @@ -956,7 +955,6 @@
       1	NULL	2020-10-22 13:32:41	2020- 
       SELECT `date_sent` FROM `email_stats` WHERE `generated_sent_email` = '2020-';
       date_sent
      -2020-10-22 13:32:41
       DROP TABLE `email_stats`;
       DROP TABLE `emails`;
       # End of 10.2 tests
      

      Curiously, if I add CHECK TABLE to the test, it will not report any corruption.

      Attachments

        Issue Links

          Activity

            nikitamalyavin, I applied the test from the patch to MariaDB as foreign_key.patch. (The final desired location would be gcol.innodb_virtual_fk where we already have a similar test.)

            This is otherwise the same as the original test, but there now is a trailing space in two WHERE conditions in the .test file. I wanted to see if it matters.

            With that, and with or without my attempted crude port of the fix, the test still fails like this:

            10.2 69b3de830d531e5cbc57c1a43c7bd55b31f7197e

            innodb.foreign_key 'innodb'              [ fail ]
                    Test ended at 2021-10-20 21:20:51
             
            CURRENT_TEST: innodb.foreign_key
            --- /mariadb/10.2o/mysql-test/suite/innodb/r/foreign_key.result	2021-10-20 17:54:42.173723268 +0300
            +++ /mariadb/10.2o/mysql-test/suite/innodb/r/foreign_key.reject	2021-10-20 21:20:51.146557129 +0300
            @@ -916,9 +916,8 @@
             SELECT * FROM `email_stats`;
             id	email_id	date_sent	generated_sent_email
             1	NULL	2020-10-22 13:32:41	2020- 
            -SELECT `date_sent` FROM `email_stats` WHERE `generated_sent_email` = '2020-';
            +SELECT `date_sent` FROM `email_stats` WHERE `generated_sent_email` = '2020- ';
             date_sent
            -2020-10-22 13:32:41
             DROP TABLE `email_stats`;
             DROP TABLE `emails`;
             # test-case 4
            @@ -954,9 +953,8 @@
             SELECT * FROM `email_stats`;
             id	email_id	date_sent	generated_sent_email
             1	NULL	2020-10-22 13:32:41	2020- 
            -SELECT `date_sent` FROM `email_stats` WHERE `generated_sent_email` = '2020-';
            +SELECT `date_sent` FROM `email_stats` WHERE `generated_sent_email` = '2020- ';
             date_sent
            -2020-10-22 13:32:41
             DROP TABLE `email_stats`;
             DROP TABLE `emails`;
             # End of 10.2 tests
             
            mysqltest: Result length mismatch
            

            marko Marko Mäkelä added a comment - nikitamalyavin , I applied the test from the patch to MariaDB as foreign_key.patch . (The final desired location would be gcol.innodb_virtual_fk where we already have a similar test.) This is otherwise the same as the original test, but there now is a trailing space in two WHERE conditions in the .test file. I wanted to see if it matters. With that, and with or without my attempted crude port of the fix, the test still fails like this: 10.2 69b3de830d531e5cbc57c1a43c7bd55b31f7197e innodb.foreign_key 'innodb' [ fail ] Test ended at 2021-10-20 21:20:51   CURRENT_TEST: innodb.foreign_key --- /mariadb/10.2o/mysql-test/suite/innodb/r/foreign_key.result 2021-10-20 17:54:42.173723268 +0300 +++ /mariadb/10.2o/mysql-test/suite/innodb/r/foreign_key.reject 2021-10-20 21:20:51.146557129 +0300 @@ -916,9 +916,8 @@ SELECT * FROM `email_stats`; id email_id date_sent generated_sent_email 1 NULL 2020-10-22 13:32:41 2020- -SELECT `date_sent` FROM `email_stats` WHERE `generated_sent_email` = '2020-'; +SELECT `date_sent` FROM `email_stats` WHERE `generated_sent_email` = '2020- '; date_sent -2020-10-22 13:32:41 DROP TABLE `email_stats`; DROP TABLE `emails`; # test-case 4 @@ -954,9 +953,8 @@ SELECT * FROM `email_stats`; id email_id date_sent generated_sent_email 1 NULL 2020-10-22 13:32:41 2020- -SELECT `date_sent` FROM `email_stats` WHERE `generated_sent_email` = '2020-'; +SELECT `date_sent` FROM `email_stats` WHERE `generated_sent_email` = '2020- '; date_sent -2020-10-22 13:32:41 DROP TABLE `email_stats`; DROP TABLE `emails`; # End of 10.2 tests   mysqltest: Result length mismatch

            By most, the problem was in the following call:

            		dfield_t* new_vfield = innobase_get_computed_value(
            				update->old_vrow, col, index,
            				&vc.heap, update->heap, NULL, thd,
            				mysql_table, record, NULL,
            				set_null ? update : node->update, foreign);
            

            We want new_vfield, but fetch it from update->old_vrow, where actually some 'new row' should be used. Unfortunately, in case of DELETE, cascade->row corresponding the new row, is NULL

            Then Sachin Agarwal's trick was to NULL the old fields in place:

            for (uint32_t j = 0; j < col->num_base; j++) {
              dict_col_t *base_col = col->base_col[j];
              uint32_t col_no = base_col->ind;
              dfield_t *row_field =
                  innobase_get_field_from_update_vector(
                      foreign, node->update, col_no);
              if (row_field != NULL) {
                dfield_set_null(row_field);
              }
            }
            

            The direct patch application could have failed, but it works fine with a little bit more context applied.

            please review the following commits:
            f359747a prettify
            0d235615 MDEV-26866 FOREIGN KEY…SET NULL corrupts an index on a virtual column

            nikitamalyavin Nikita Malyavin added a comment - By most, the problem was in the following call: dfield_t* new_vfield = innobase_get_computed_value( update->old_vrow, col, index, &vc.heap, update->heap, NULL, thd, mysql_table, record, NULL, set_null ? update : node->update, foreign); We want new_vfield , but fetch it from update->old_vrow , where actually some 'new row' should be used. Unfortunately, in case of DELETE, cascade->row corresponding the new row, is NULL Then Sachin Agarwal 's trick was to NULL the old fields in place: for (uint32_t j = 0; j < col->num_base; j++) { dict_col_t *base_col = col->base_col[j]; uint32_t col_no = base_col->ind; dfield_t *row_field = innobase_get_field_from_update_vector( foreign, node->update, col_no); if (row_field != NULL) { dfield_set_null(row_field); } } The direct patch application could have failed, but it works fine with a little bit more context applied. please review the following commits: f359747a prettify 0d235615 MDEV-26866 FOREIGN KEY…SET NULL corrupts an index on a virtual column

            Please address my review comments and prepare also a 10.6 version for additional stress testing.

            marko Marko Mäkelä added a comment - Please address my review comments and prepare also a 10.6 version for additional stress testing.

            This looks like very welcome cleanup. OK to push if the stress tests pass.

            marko Marko Mäkelä added a comment - This looks like very welcome cleanup. OK to push if the stress tests pass.

            origin/bb-10.2-nikita e83e82780d75ee91ea817378646963c0a41b08cf 2021-10-27T11:42:20+03:00
            origin/bb-10.6-nikita-MDEV-26866 3c93637a294ba061dc44c5a9ddeed1be65910a3f 2021-10-27T12:50:51+03:00
            behaved well in RQG testing.
            

            mleich Matthias Leich added a comment - origin/bb-10.2-nikita e83e82780d75ee91ea817378646963c0a41b08cf 2021-10-27T11:42:20+03:00 origin/bb-10.6-nikita-MDEV-26866 3c93637a294ba061dc44c5a9ddeed1be65910a3f 2021-10-27T12:50:51+03:00 behaved well in RQG testing.

            People

              nikitamalyavin Nikita Malyavin
              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.