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

Server crashes after DELETE with SET NULL Foreign key and a virtual column in index

Details

    Description

      I'm getting a server crash when I issue a very simple DELETE statement "DELETE FROM companies WHERE CompanyID=749".

      I believe it might have something to do with an "ON DELETE SET NULL" foreign key relationship and some indexes of virtual columns in the child table... but unfortunately I was unable to reproduce the problem as a simple testcase; it seems to depend somehow on the data in my existing DB.

      I can however reliably repeat the crash if I issue the exact same DELETE statement.

      Since I was unable to determine the specific cause, I can't tell if this is related to an already-reported bug or not.

      The tables are all InnoDB, and running mysql_upgrade did not affect the issue.

      The log contained the following:

      190821  4:08:56 [ERROR] mysqld got signal 11 ;
      This could be because you hit a bug. It is also possible that this binary
      or one of the libraries it was linked against is corrupt, improperly built,
      or misconfigured. This error can also be caused by malfunctioning hardware.
       
      To report this bug, see https://mariadb.com/kb/en/reporting-bugs
       
      We will try our best to scrape up some info that will hopefully help
      diagnose the problem, but since we have already crashed,
      something is definitely wrong and this may fail.
       
      Server version: 10.3.17-MariaDB
      key_buffer_size=134217728
      read_buffer_size=131072
      max_used_connections=2
      max_threads=153
      thread_count=8
      It is possible that mysqld could use up to
      key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 467422 K  bytes of memory
      Hope that's ok; if not, decrease some variables in the equation.
       
      Thread pointer: 0x55a1b0836658
      Attempting backtrace. You can use the following information to find out
      where mysqld died. If you see no messages after this, something went
      terribly wrong...
      stack_bottom = 0x7f17c45a8d30 thread_stack 0x49000
      /usr/sbin/mysqld(my_print_stacktrace+0x2e)[0x55a1adf3f93e]
      /usr/sbin/mysqld(handle_fatal_signal+0x30f)[0x55a1ad9df2af]sigaction.c:0(__restore_rt)[0x7f17d4b355d0]
      /usr/sbin/mysqld(+0xa174fd)[0x55a1adc6d4fd]
      /usr/sbin/mysqld(+0xa17ddc)[0x55a1adc6dddc]
      /usr/sbin/mysqld(+0xa18ff4)[0x55a1adc6eff4]
      /usr/sbin/mysqld(+0x9ea141)[0x55a1adc40141]
      /usr/sbin/mysqld(+0x9d35c2)[0x55a1adc295c2]
      /usr/sbin/mysqld(+0xa12a78)[0x55a1adc68a78]
      /usr/sbin/mysqld(+0xa18809)[0x55a1adc6e809]
      /usr/sbin/mysqld(+0xa18ff4)[0x55a1adc6eff4]
      /usr/sbin/mysqld(+0x9e9c0b)[0x55a1adc3fc0b]
      /usr/sbin/mysqld(+0x926c1c)[0x55a1adb7cc1c]
      /usr/sbin/mysqld(_ZN7handler13ha_delete_rowEPKh+0x19f)[0x55a1ad9eb01f]
      /usr/sbin/mysqld(_Z12mysql_deleteP3THDP10TABLE_LISTP4ItemP10SQL_I_ListI8st_orderEyyP13select_result+0x14e8)[0x55a1adb1fa68]
      /usr/sbin/mysqld(_Z21mysql_execute_commandP3THD+0x25d1)[0x55a1ad803611]
      /usr/sbin/mysqld(_Z11mysql_parseP3THDPcjP12Parser_statebb+0x22b)[0x55a1ad809c2b]
      /usr/sbin/mysqld(_Z16dispatch_command19enum_server_commandP3THDPcjbb+0x1c9f)[0x55a1ad80c80f]
      /usr/sbin/mysqld(_Z10do_commandP3THD+0x13e)[0x55a1ad80d74e]
      /usr/sbin/mysqld(_Z24do_handle_one_connectionP7CONNECT+0x221)[0x55a1ad8e0f61]
      /usr/sbin/mysqld(handle_one_connection+0x3d)[0x55a1ad8e102d]
      pthread_create.c:0(start_thread)[0x7f17d4b2ddd5]
      /lib64/libc.so.6(clone+0x6d)[0x7f17d2ed002d]
       
      Trying to get some variables.
      Some pointers may be invalid and cause the dump to abort.
      Query (0x55a1b08440d0): DELETE FROM companies WHERE CompanyID=749
      Connection ID (thread ID): 40
      Status: NOT_KILLED
       
      Optimizer switch: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
       
      The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
      information that should help you find out what is causing the crash.
      Writing a core file...
      Working directory at /var/lib/mysql
      Resource Limits:Limit                     Soft Limit           Hard Limit           Units
      Max cpu time              unlimited            unlimited            seconds
      Max file size             unlimited            unlimited            bytes
      Max data size             unlimited            unlimited            bytes
      Max stack size            8388608              unlimited            bytes
      Max core file size        0                    unlimited            bytes
      Max resident set          unlimited            unlimited            bytes
      Max processes             7263                 7263                 processes
      Max open files            50000                50000                files
      Max locked memory         65536                65536                bytes
      Max address space         unlimited            unlimited            bytes
      Max file locks            unlimited            unlimited            locks
      Max pending signals       7263                 7263                 signals
      Max msgqueue size         819200               819200               bytes
      Max nice priority         0                    0
      Max realtime priority     0                    0
      Max realtime timeout      unlimited            unlimited            us
      Core pattern: core
      

      Attachments

        1. error log.txt
          9 kB
        2. testcase.zip
          307 kB
        3. virt.test
          15 kB

        Issue Links

          Activity

            alice Alice Sherepa added a comment -

            Thanks a lot! I repeated with the provided test case on 10.2-10.5:

            10.2 c710c450e3a5654244

            Version: '10.2.34-MariaDB-debug-log'  
            2020-08-31  8:21:18 140502294345472 [ERROR] InnoDB: Record in index `ParentID` of table `test`.`child` was not found on update: TUPLE (info_bits=0, 3 fields): {NULL,[1] (0x01),[4]   5(0x0001E535)} at: COMPACT RECORD(info_bits=0, 3 fields): {NULL,[1] (0x01),[4]   ~(0x0001E47E)}
            mysqld: /d1/git/10.2/storage/innobase/row/row0upd.cc:2437: dberr_t row_upd_sec_index_entry(upd_node_t*, que_thr_t*): Assertion `0' failed.
            200831  8:21:18 [ERROR] mysqld got signal 6 ;
            Server version: 10.2.34-MariaDB-debug-log
             
            linux/raise.c:51(__GI_raise)[0x7fc94316f7bb]
            stdlib/abort.c:81(__GI_abort)[0x7fc94315a535]
            intl/loadmsgcat.c:1177(_nl_load_domain)[0x7fc94315a40f]
            /lib/x86_64-linux-gnu/libc.so.6(+0x30102)[0x7fc943168102]
            row/row0upd.cc:2441(row_upd_sec_index_entry(upd_node_t*, que_thr_t*))[0x55d102934bcc]
            row/row0upd.cc:2560(row_upd_sec_step(upd_node_t*, que_thr_t*))[0x55d1029353f3]
            row/row0upd.cc:3316(row_upd(upd_node_t*, que_thr_t*))[0x55d102937646]
            row/row0upd.cc:3433(row_upd_step(que_thr_t*))[0x55d10293799a]
            row/row0mysql.cc:1827(row_update_for_mysql(row_prebuilt_t*))[0x55d1028e2086]
            handler/ha_innodb.cc:8942(ha_innobase::update_row(unsigned char const*, unsigned char*))[0x55d1027a6c47]
            sql/handler.cc:6140(handler::ha_update_row(unsigned char const*, unsigned char*))[0x55d1025b579a]
            sql/sql_update.cc:817(mysql_update(THD*, TABLE_LIST*, List<Item>&, List<Item>&, Item*, unsigned int, st_order*, unsigned long long, enum_duplicates, bool, unsigned long long*, unsigned long long*))[0x55d10242051b]
            sql/sql_parse.cc:3998(mysql_execute_command(THD*))[0x55d102330f6c]
            sql/sql_parse.cc:7733(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x55d10233cd25]
            sql/sql_parse.cc:1826(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x55d10232b13f]
            sql/sql_parse.cc:1377(do_command(THD*))[0x55d102329bc4]
            sql/sql_connect.cc:1336(do_handle_one_connection(CONNECT*))[0x55d10247e8c4]
            sql/sql_connect.cc:1242(handle_one_connection)[0x55d10247e62f]
            perfschema/pfs.cc:1871(pfs_spawn_thread)[0x55d102c800ca]
            nptl/pthread_create.c:487(start_thread)[0x7fc9438adfa3]
            x86_64/clone.S:97(clone)[0x7fc9432314cf]
             
            Trying to get some variables.
            Some pointers may be invalid and cause the dump to abort.
            Query (0x7fc8ec0127b8): UPDATE child SET ParentID=1000 WHERE ID=124213
            

            10.3 6a042281bdbfe91cc39e1f6e02

            Version: '10.3.25-MariaDB-debug-log'  
            2020-08-31 08:27:03 0x7f94572a2700  InnoDB: Assertion failure in file /d1/git/10.3/storage/innobase/row/row0ins.cc line 221
            InnoDB: Failing assertion: !cursor->index->is_committed()
            InnoDB: We intentionally generate a memory trap.
            InnoDB: Submit a detailed bug report to https://jira.mariadb.org/
            InnoDB: If you get repeated assertion failures or crashes, even
            InnoDB: immediately after the mysqld startup, there may be
            InnoDB: corruption in the InnoDB tablespace. Please refer to
            InnoDB: https://mariadb.com/kb/en/library/innodb-recovery-modes/
            InnoDB: about forcing recovery.
            200831  8:27:03 [ERROR] mysqld got signal 6 ;
             
            linux/raise.c:51(__GI_raise)[0x7f946213c7bb]
            stdlib/abort.c:81(__GI_abort)[0x7f9462127535]
            /d1/git/10.3/sql/mysqld(+0xeba398)[0x56510a5f4398]
            ut/ut0new.cc:95(ut_new_boot())[0x56510a4da4c2]
            row/row0ins.cc:222(row_ins_sec_index_entry_by_modify(unsigned long, unsigned long, btr_cur_t*, unsigned short**, mem_block_info_t*, mem_block_info_t*, dtuple_t const*, que_thr_t*, mtr_t*))[0x56510a4e28e6]
            row/row0ins.cc:3079(row_ins_sec_index_entry_low(unsigned long, unsigned long, dict_index_t*, mem_block_info_t*, mem_block_info_t*, dtuple_t*, unsigned long, que_thr_t*))[0x56510a4e31f9]
            row/row0ins.cc:3276(row_ins_sec_index_entry(dict_index_t*, dtuple_t*, que_thr_t*, bool))[0x56510a574ffd]
            row/row0upd.cc:2536(row_upd_sec_index_entry(upd_node_t*, que_thr_t*))[0x56510a57526e]
            row/row0upd.cc:2563(row_upd_sec_step(upd_node_t*, que_thr_t*))[0x56510a577ff7]
            row/row0upd.cc:3332(row_upd(upd_node_t*, que_thr_t*))[0x56510a578444]
            row/row0upd.cc:3447(row_upd_step(que_thr_t*))[0x56510a50d2e8]
            row/row0mysql.cc:2223(row_update_cascade_for_mysql(que_thr_t*, upd_node_t*, dict_table_t*))[0x56510a4ddba2]
            row/row0ins.cc:1396(row_ins_foreign_check_on_constraint(que_thr_t*, dict_foreign_t*, btr_pcur_t*, dtuple_t*, mtr_t*))[0x56510a4dec67]
            row/row0ins.cc:1819(row_ins_check_foreign_constraint(unsigned long, dict_foreign_t*, dict_table_t*, dtuple_t*, que_thr_t*))[0x56510a56edb6]
            row/row0upd.cc:295(row_upd_check_references_constraints(upd_node_t*, btr_pcur_t*, dict_table_t*, dict_index_t*, unsigned short*, que_thr_t*, mtr_t*))[0x56510a576e5b]
            row/row0upd.cc:3004(row_upd_del_mark_clust_rec(upd_node_t*, dict_index_t*, unsigned short*, que_thr_t*, unsigned long, bool, mtr_t*))[0x56510a57789d]
            row/row0upd.cc:3174(row_upd_clust_step(upd_node_t*, que_thr_t*))[0x56510a577e76]
            row/row0upd.cc:3303(row_upd(upd_node_t*, que_thr_t*))[0x56510a578444]
            row/row0upd.cc:3447(row_upd_step(que_thr_t*))[0x56510a50c3e6]
            row/row0mysql.cc:1849(row_update_for_mysql(row_prebuilt_t*))[0x56510a37800b]
            handler/ha_innodb.cc:8907(ha_innobase::delete_row(unsigned char const*))[0x56510a15849e]
            sql/handler.cc:6554(handler::ha_delete_row(unsigned char const*))[0x56510a2fd86d]
            sql/sql_delete.cc:245(TABLE::delete_row())[0x56510a2fa98d]
            sql/sql_delete.cc:720(mysql_delete(THD*, TABLE_LIST*, Item*, SQL_I_List<st_order>*, unsigned long long, unsigned long long, select_result*))[0x565109e30d75]
            sql/sql_parse.cc:4649(mysql_execute_command(THD*))[0x565109e3ba88]
            sql/sql_parse.cc:7810(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x565109e283ca]
            sql/sql_parse.cc:1850(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x565109e26ced]
            sql/sql_parse.cc:1393(do_command(THD*))[0x565109f9ec48]
            sql/sql_connect.cc:1403(do_handle_one_connection(CONNECT*))[0x565109f9e9aa]
            sql/sql_connect.cc:1309(handle_one_connection)[0x56510a93aa05]
            nptl/pthread_create.c:487(start_thread)[0x7f946287afa3]
            x86_64/clone.S:97(clone)[0x7f94621fe4cf]
             
            Query (0x7f940c012a78): DELETE FROM parent WHERE ID=1000
            

            alice Alice Sherepa added a comment - Thanks a lot! I repeated with the provided test case on 10.2-10.5: 10.2 c710c450e3a5654244 Version: '10.2.34-MariaDB-debug-log' 2020-08-31 8:21:18 140502294345472 [ERROR] InnoDB: Record in index `ParentID` of table `test`.`child` was not found on update: TUPLE (info_bits=0, 3 fields): {NULL,[1] (0x01),[4] 5(0x0001E535)} at: COMPACT RECORD(info_bits=0, 3 fields): {NULL,[1] (0x01),[4] ~(0x0001E47E)} mysqld: /d1/git/10.2/storage/innobase/row/row0upd.cc:2437: dberr_t row_upd_sec_index_entry(upd_node_t*, que_thr_t*): Assertion `0' failed. 200831 8:21:18 [ERROR] mysqld got signal 6 ; Server version: 10.2.34-MariaDB-debug-log   linux/raise.c:51(__GI_raise)[0x7fc94316f7bb] stdlib/abort.c:81(__GI_abort)[0x7fc94315a535] intl/loadmsgcat.c:1177(_nl_load_domain)[0x7fc94315a40f] /lib/x86_64-linux-gnu/libc.so.6(+0x30102)[0x7fc943168102] row/row0upd.cc:2441(row_upd_sec_index_entry(upd_node_t*, que_thr_t*))[0x55d102934bcc] row/row0upd.cc:2560(row_upd_sec_step(upd_node_t*, que_thr_t*))[0x55d1029353f3] row/row0upd.cc:3316(row_upd(upd_node_t*, que_thr_t*))[0x55d102937646] row/row0upd.cc:3433(row_upd_step(que_thr_t*))[0x55d10293799a] row/row0mysql.cc:1827(row_update_for_mysql(row_prebuilt_t*))[0x55d1028e2086] handler/ha_innodb.cc:8942(ha_innobase::update_row(unsigned char const*, unsigned char*))[0x55d1027a6c47] sql/handler.cc:6140(handler::ha_update_row(unsigned char const*, unsigned char*))[0x55d1025b579a] sql/sql_update.cc:817(mysql_update(THD*, TABLE_LIST*, List<Item>&, List<Item>&, Item*, unsigned int, st_order*, unsigned long long, enum_duplicates, bool, unsigned long long*, unsigned long long*))[0x55d10242051b] sql/sql_parse.cc:3998(mysql_execute_command(THD*))[0x55d102330f6c] sql/sql_parse.cc:7733(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x55d10233cd25] sql/sql_parse.cc:1826(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x55d10232b13f] sql/sql_parse.cc:1377(do_command(THD*))[0x55d102329bc4] sql/sql_connect.cc:1336(do_handle_one_connection(CONNECT*))[0x55d10247e8c4] sql/sql_connect.cc:1242(handle_one_connection)[0x55d10247e62f] perfschema/pfs.cc:1871(pfs_spawn_thread)[0x55d102c800ca] nptl/pthread_create.c:487(start_thread)[0x7fc9438adfa3] x86_64/clone.S:97(clone)[0x7fc9432314cf]   Trying to get some variables. Some pointers may be invalid and cause the dump to abort. Query (0x7fc8ec0127b8): UPDATE child SET ParentID=1000 WHERE ID=124213 10.3 6a042281bdbfe91cc39e1f6e02 Version: '10.3.25-MariaDB-debug-log' 2020-08-31 08:27:03 0x7f94572a2700 InnoDB: Assertion failure in file /d1/git/10.3/storage/innobase/row/row0ins.cc line 221 InnoDB: Failing assertion: !cursor->index->is_committed() InnoDB: We intentionally generate a memory trap. InnoDB: Submit a detailed bug report to https://jira.mariadb.org/ InnoDB: If you get repeated assertion failures or crashes, even InnoDB: immediately after the mysqld startup, there may be InnoDB: corruption in the InnoDB tablespace. Please refer to InnoDB: https://mariadb.com/kb/en/library/innodb-recovery-modes/ InnoDB: about forcing recovery. 200831 8:27:03 [ERROR] mysqld got signal 6 ;   linux/raise.c:51(__GI_raise)[0x7f946213c7bb] stdlib/abort.c:81(__GI_abort)[0x7f9462127535] /d1/git/10.3/sql/mysqld(+0xeba398)[0x56510a5f4398] ut/ut0new.cc:95(ut_new_boot())[0x56510a4da4c2] row/row0ins.cc:222(row_ins_sec_index_entry_by_modify(unsigned long, unsigned long, btr_cur_t*, unsigned short**, mem_block_info_t*, mem_block_info_t*, dtuple_t const*, que_thr_t*, mtr_t*))[0x56510a4e28e6] row/row0ins.cc:3079(row_ins_sec_index_entry_low(unsigned long, unsigned long, dict_index_t*, mem_block_info_t*, mem_block_info_t*, dtuple_t*, unsigned long, que_thr_t*))[0x56510a4e31f9] row/row0ins.cc:3276(row_ins_sec_index_entry(dict_index_t*, dtuple_t*, que_thr_t*, bool))[0x56510a574ffd] row/row0upd.cc:2536(row_upd_sec_index_entry(upd_node_t*, que_thr_t*))[0x56510a57526e] row/row0upd.cc:2563(row_upd_sec_step(upd_node_t*, que_thr_t*))[0x56510a577ff7] row/row0upd.cc:3332(row_upd(upd_node_t*, que_thr_t*))[0x56510a578444] row/row0upd.cc:3447(row_upd_step(que_thr_t*))[0x56510a50d2e8] row/row0mysql.cc:2223(row_update_cascade_for_mysql(que_thr_t*, upd_node_t*, dict_table_t*))[0x56510a4ddba2] row/row0ins.cc:1396(row_ins_foreign_check_on_constraint(que_thr_t*, dict_foreign_t*, btr_pcur_t*, dtuple_t*, mtr_t*))[0x56510a4dec67] row/row0ins.cc:1819(row_ins_check_foreign_constraint(unsigned long, dict_foreign_t*, dict_table_t*, dtuple_t*, que_thr_t*))[0x56510a56edb6] row/row0upd.cc:295(row_upd_check_references_constraints(upd_node_t*, btr_pcur_t*, dict_table_t*, dict_index_t*, unsigned short*, que_thr_t*, mtr_t*))[0x56510a576e5b] row/row0upd.cc:3004(row_upd_del_mark_clust_rec(upd_node_t*, dict_index_t*, unsigned short*, que_thr_t*, unsigned long, bool, mtr_t*))[0x56510a57789d] row/row0upd.cc:3174(row_upd_clust_step(upd_node_t*, que_thr_t*))[0x56510a577e76] row/row0upd.cc:3303(row_upd(upd_node_t*, que_thr_t*))[0x56510a578444] row/row0upd.cc:3447(row_upd_step(que_thr_t*))[0x56510a50c3e6] row/row0mysql.cc:1849(row_update_for_mysql(row_prebuilt_t*))[0x56510a37800b] handler/ha_innodb.cc:8907(ha_innobase::delete_row(unsigned char const*))[0x56510a15849e] sql/handler.cc:6554(handler::ha_delete_row(unsigned char const*))[0x56510a2fd86d] sql/sql_delete.cc:245(TABLE::delete_row())[0x56510a2fa98d] sql/sql_delete.cc:720(mysql_delete(THD*, TABLE_LIST*, Item*, SQL_I_List<st_order>*, unsigned long long, unsigned long long, select_result*))[0x565109e30d75] sql/sql_parse.cc:4649(mysql_execute_command(THD*))[0x565109e3ba88] sql/sql_parse.cc:7810(mysql_parse(THD*, char*, unsigned int, Parser_state*, bool, bool))[0x565109e283ca] sql/sql_parse.cc:1850(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool, bool))[0x565109e26ced] sql/sql_parse.cc:1393(do_command(THD*))[0x565109f9ec48] sql/sql_connect.cc:1403(do_handle_one_connection(CONNECT*))[0x565109f9e9aa] sql/sql_connect.cc:1309(handle_one_connection)[0x56510a93aa05] nptl/pthread_create.c:487(start_thread)[0x7f946287afa3] x86_64/clone.S:97(clone)[0x7f94621fe4cf]   Query (0x7f940c012a78): DELETE FROM parent WHERE ID=1000

            Till the last release set, we were tracking the virtual column variation of this assertion failure under MDEV-19338. Apparently it hasn't been fully fixed.

            elenst Elena Stepanova added a comment - Till the last release set, we were tracking the virtual column variation of this assertion failure under MDEV-19338 . Apparently it hasn't been fully fixed.
            nikitamalyavin Nikita Malyavin added a comment - - edited

            Analysis report

            First of all I was successful at reducing the test case to ~25 lines. It turned out that one record for each table is enough:

            --source include/have_innodb.inc
             
            set default_storage_engine=innodb;
             
            CREATE TABLE parent
            (
              ID int unsigned NOT NULL,
              PRIMARY KEY (ID)
            );
             
            CREATE TABLE child
            (
              ID int unsigned NOT NULL,
              ParentID int unsigned NULL,
              Value int unsigned NOT NULL DEFAULT 0xbababebe,
              Flag int unsigned AS (Value) VIRTUAL,
              PRIMARY KEY (ID),
              KEY (ParentID,Flag),
              FOREIGN KEY (ParentID) REFERENCES parent (ID) ON DELETE SET NULL ON UPDATE CASCADE
            );
             
            INSERT INTO parent (ID) VALUES (100);
            INSERT INTO child (ID,ParentID,Value) VALUES (123123,100,1);
            #UPDATE child set ParentID= NULL WHERE ParentID = 100;
            DELETE FROM parent WHERE ID=100;
            select * from child;
            INSERT INTO parent (ID) VALUES (100);
            UPDATE child SET ParentID=100 WHERE ID=123123;
            

            This is the minimal test case to fail.

            To analyze the problem I used good/bad strategy. First I tried to compare the behaviors without the virtual column, by substituting Flag type with INT UNSIGNED DEFAULT (123).
            Tracing the data changes has only shown that the value returned from the b-tree index contains Flag=NULL in BAD case (so the match didn't happen, and therefore the assertion has failed) and Flag=123 in GOOD case.

            Second approach was to compare the cascade SET NULL update behavior with UPDATE child SET Parent=NULL and to see what the difference is there.
            Hopefully, both functions make an update with row_upd call.
            I have placed the breakpoints in some key places when data transitions happen. We could expect that both cases would behave identically during update, and that gets confirmed by stack traces.

            GOOD:

            #0  rec_copy (buf=0x611000071188, rec=0x7f5db859007e "", offsets=0x7f5da5d45d40) at ../storage/innobase/include/rem0rec.ic:1563
            #1  0x0000559ba07ef1cd in row_build_low (type=1, index=0x617000043708, rec=0x7f5db859007e "", offsets=0x7f5da5d45d40, col_table=0x0, add_cols=0x0, add_v=0x0, col_map=0x0, ext=0x6210000a5e50, heap=0x611000071100) at ../storage/innobase/row/row0row.cc:426
            #2  0x0000559ba07eeb8a in row_build (type=1, index=0x617000043708, rec=0x7f5db859007e "", offsets=0x7f5da5d45d40, col_table=0x0, add_cols=0x0, col_map=0x0, ext=0x6210000a5e50, heap=0x611000071100) at ../storage/innobase/row/row0row.cc:602
            #3  0x0000559ba088b457 in row_upd_store_row (node=0x6210000a5d70, thd=0x62a0000ba208, mysql_table=0x61e00003cc88) at ../storage/innobase/row/row0upd.cc:2236
            #4  0x0000559ba0887478 in row_upd_clust_step (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3190
            #5  0x0000559ba0881b65 in row_upd (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3286
            #6  0x0000559ba0880eb1 in row_upd_step (thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3432
            #7  0x0000559ba0780c01 in row_update_for_mysql (prebuilt=0x6210000a5188) at ../storage/innobase/row/row0mysql.cc:1825
            #8  0x0000559ba03a53bc in ha_innobase::update_row (this=0x61c0000638a8, old_row=0x6190000da2d0 "\371\363\340\001", new_row=0x6190000da2b8 "\373\363\340\001") at ../storage/innobase/handler/ha_innodb.cc:8943
            #9  0x0000559b9fcb023c in handler::ha_update_row (this=0x61c0000638a8, old_data=0x6190000da2d0 "\371\363\340\001", new_data=0x6190000da2b8 "\373\363\340\001") at ../sql/handler.cc:6140
            #10 0x0000559b9f74a156 in mysql_update (thd=0x62a0000ba208, table_list=0x62b000000370, fields=..., values=..., conds=0x62b000000d60, order_num=0, order=0x0, limit=18446744073709551615, handle_duplicates=DUP_ERROR, ignore=false, found_return=0x7f5da5d4e5a0, updated_return=0x7f5da5d4e5c0) at ../sql/sql_update.cc:817
            #11 0x0000559b9f3c0e4b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:3998
            #12 0x0000559b9f3afce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "UPDATE child set ParentID= NULL WHERE ParentID = 100", length=52, parser_state=0x7f5da5d50b20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733
            

            BAD:

            #0  rec_copy (buf=0x61600005b410, rec=0x7fd555c7407e "", offsets=0x7fd543430b80) at ../storage/innobase/include/rem0rec.ic:1563
            #1  0x000055e3292981cd in row_build_low (type=1, index=0x617000043708, rec=0x7fd555c7407e "", offsets=0x7fd543430b80, col_table=0x0, add_cols=0x0, add_v=0x0, col_map=0x0, ext=0x61600005b0e8, heap=0x611000071380) at ../storage/innobase/row/row0row.cc:426
            #2  0x000055e329297b8a in row_build (type=1, index=0x617000043708, rec=0x7fd555c7407e "", offsets=0x7fd543430b80, col_table=0x0, add_cols=0x0, col_map=0x0, ext=0x61600005b0e8, heap=0x611000071380) at ../storage/innobase/row/row0row.cc:602
            #3  0x000055e329334457 in row_upd_store_row (node=0x61600005b008, thd=0x62a0000ba208, mysql_table=0x0) at ../storage/innobase/row/row0upd.cc:2236
            #4  0x000055e329330478 in row_upd_clust_step (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3190
            #5  0x000055e32932ab65 in row_upd (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286
            #6  0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432
            #7  0x000055e32922d564 in row_update_cascade_for_mysql (thr=0x6240001dc188, node=0x61600005b008, table=0x618000046908) at ../storage/innobase/row/row0mysql.cc:2109
            #8  0x000055e3291bce29 in row_ins_foreign_check_on_constraint (thr=0x6240001dc188, foreign=0x616000058f08, pcur=0x7fd543432f80, entry=0x61600005ad28, mtr=0x7fd5434330c0) at ../storage/innobase/row/row0ins.cc:1404
            #9  0x000055e3291b7aa9 in row_ins_check_foreign_constraint (check_ref=0, foreign=0x616000058f08, table=0x618000045d08, entry=0x61600005ad28, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:1793
            #10 0x000055e3293378ee in row_upd_check_references_constraints (node=0x620000010bf8, pcur=0x611000071100, table=0x618000045d08, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:325
            #11 0x000055e3293321f1 in row_upd_del_mark_clust_rec (node=0x620000010bf8, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, referenced=1, foreign=false, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:2996
            #12 0x000055e32933009d in row_upd_clust_step (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3157
            #13 0x000055e32932ab65 in row_upd (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286
            #14 0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432
            #15 0x000055e329229c01 in row_update_for_mysql (prebuilt=0x620000010108) at ../storage/innobase/row/row0mysql.cc:1825
            #16 0x000055e328e52d64 in ha_innobase::delete_row (this=0x61c0000628a8, record=0x6190000d93b8 "\377d") at ../storage/innobase/handler/ha_innodb.cc:9059
            #17 0x000055e328759cba in handler::ha_delete_row (this=0x61c0000628a8, buf=0x6190000d93b8 "\377d") at ../sql/handler.cc:6168
            #18 0x000055e328ca6f07 in mysql_delete (thd=0x62a0000ba208, table_list=0x62b000000340, conds=0x62b000000b30, order_list=0x62a0000be7a0, limit=18446744073709551615, options=0, result=0x0) at ../sql/sql_delete.cc:583
            #19 0x000055e327e6e16b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:4362
            #20 0x000055e327e58ce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "DELETE FROM parent WHERE ID=100", length=31, parser_state=0x7fd54343eb20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733
            

            We can see here, that top 5 frames are identical, and that is expected to be persistent during the whole functinon execution (considering it is designed well).
            I was expecting the difference in row_upd_sec_index_entry, since it is the function where the secondary index update happens. The first difference I found was in rec_convert_dtuple_to_rec_comp record-tuple comparison function.

            GOOD:

            #0  rec_convert_dtuple_to_rec_comp (rec=0x6190000dc10e "\276\276\276\276"..., index=0x617000044188, fields=0x6190000dbc40, n_fields=3, status=0, temp=false) at ../storage/innobase/rem/rem0rec.cc:1262
            #1  0x0000559ba06b76be in rec_convert_dtuple_to_rec_new (buf=0x6190000dc108 "\001\276", index=0x617000044188, dtuple=0x6190000dbc08) at ../storage/innobase/rem/rem0rec.cc:1338
            #2  0x0000559ba06b73ce in rec_convert_dtuple_to_rec (buf=0x6190000dc108 "\001\276", index=0x617000044188, dtuple=0x6190000dbc08, n_ext=0) at ../storage/innobase/rem/rem0rec.cc:1370
            #3  0x0000559ba0a71140 in page_cur_tuple_insert (cursor=0x7f5da5d44328, tuple=0x6190000dbc08, index=0x617000044188, offsets=0x7f5da5d44c30, heap=0x7f5da5d442c0, n_ext=0, mtr=0x7f5da5d44400, use_cache=false) at ../storage/innobase/include/page0cur.ic:280
            #4  0x0000559ba0a6ebd2 in btr_cur_optimistic_insert (flags=0, cursor=0x7f5da5d44320, offsets=0x7f5da5d44c30, heap=0x7f5da5d442c0, entry=0x6190000dbc08, rec=0x7f5da5d45420, big_rec=0x7f5da5d45440, n_ext=0, thr=0x6250000f0188, mtr=0x7f5da5d44400) at ../storage/innobase/btr/btr0cur.cc:3237
            #5  0x0000559ba071c25f in row_ins_sec_index_entry_low (flags=0, mode=2, index=0x617000044188, offsets_heap=0x6190000dc080, heap=0x6190000dc580, entry=0x6190000dbc08, trx_id=0, thr=0x6250000f0188) at ../storage/innobase/row/row0ins.cc:3029
            #6  0x0000559ba0720496 in row_ins_sec_index_entry (index=0x617000044188, entry=0x6190000dbc08, thr=0x6250000f0188) at ../storage/innobase/row/row0ins.cc:3203
            #7  0x0000559ba0895093 in row_upd_sec_index_entry (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:2526
            #8  0x0000559ba0887c94 in row_upd_sec_step (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:2553
            #9  0x0000559ba088220f in row_upd (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3315
            #10 0x0000559ba0880eb1 in row_upd_step (thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3432
            #11 0x0000559ba0780c01 in row_update_for_mysql (prebuilt=0x6210000a5188) at ../storage/innobase/row/row0mysql.cc:1825
            #12 0x0000559ba03a53bc in ha_innobase::update_row (this=0x61c0000638a8, old_row=0x6190000da2d0 "\371\363\340\001", new_row=0x6190000da2b8 "\373\363\340\001") at ../storage/innobase/handler/ha_innodb.cc:8943
            #13 0x0000559b9fcb023c in handler::ha_update_row (this=0x61c0000638a8, old_data=0x6190000da2d0 "\371\363\340\001", new_data=0x6190000da2b8 "\373\363\340\001") at ../sql/handler.cc:6140
            #14 0x0000559b9f74a156 in mysql_update (thd=0x62a0000ba208, table_list=0x62b000000370, fields=..., values=..., conds=0x62b000000d60, order_num=0, order=0x0, limit=18446744073709551615, handle_duplicates=DUP_ERROR, ignore=false, found_return=0x7f5da5d4e5a0, updated_return=0x7f5da5d4e5c0) at ../sql/sql_update.cc:817
            #15 0x0000559b9f3c0e4b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:3998
            #16 0x0000559b9f3afce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "UPDATE child set ParentID= NULL WHERE ParentID = 100", length=52, parser_state=0x7f5da5d50b20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733
            

            if (dfield_is_null(field)) entry is bypassed

            BAD

            #0  rec_convert_dtuple_to_rec_comp (rec=0x6190000dc10e "\276\276\276"..., index=0x617000044188, fields=0x6190000dbc40, n_fields=3, status=0, temp=false) at ../storage/innobase/rem/rem0rec.cc:1257
            #1  0x000055e3291606be in rec_convert_dtuple_to_rec_new (buf=0x6190000dc108 "\001\276", index=0x617000044188, dtuple=0x6190000dbc08) at ../storage/innobase/rem/rem0rec.cc:1338
            #2  0x000055e3291603ce in rec_convert_dtuple_to_rec (buf=0x6190000dc108 "\001\276", index=0x617000044188, dtuple=0x6190000dbc08, n_ext=0) at ../storage/innobase/rem/rem0rec.cc:1370
            #3  0x000055e32951a140 in page_cur_tuple_insert (cursor=0x7fd54342f168, tuple=0x6190000dbc08, index=0x617000044188, offsets=0x7fd54342fa70, heap=0x7fd54342f100, n_ext=0, mtr=0x7fd54342f240, use_cache=false) at ../storage/innobase/include/page0cur.ic:280
            #4  0x000055e329517bd2 in btr_cur_optimistic_insert (flags=0, cursor=0x7fd54342f160, offsets=0x7fd54342fa70, heap=0x7fd54342f100, entry=0x6190000dbc08, rec=0x7fd543430260, big_rec=0x7fd543430280, n_ext=0, thr=0x6240001dc188, mtr=0x7fd54342f240) at ../storage/innobase/btr/btr0cur.cc:3237
            #5  0x000055e3291c525f in row_ins_sec_index_entry_low (flags=0, mode=2, index=0x617000044188, offsets_heap=0x6190000dc080, heap=0x6190000dc580, entry=0x6190000dbc08, trx_id=0, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:3029
            #6  0x000055e3291c9496 in row_ins_sec_index_entry (index=0x617000044188, entry=0x6190000dbc08, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:3203
            #7  0x000055e32933e093 in row_upd_sec_index_entry (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:2526
            #8  0x000055e329330c94 in row_upd_sec_step (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:2553
            #9  0x000055e32932b20f in row_upd (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3315
            #10 0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432
            #11 0x000055e32922d564 in row_update_cascade_for_mysql (thr=0x6240001dc188, node=0x61600005b008, table=0x618000046908) at ../storage/innobase/row/row0mysql.cc:2109
            #12 0x000055e3291bce29 in row_ins_foreign_check_on_constraint (thr=0x6240001dc188, foreign=0x616000058f08, pcur=0x7fd543432f80, entry=0x61600005ad28, mtr=0x7fd5434330c0) at ../storage/innobase/row/row0ins.cc:1404
            #13 0x000055e3291b7aa9 in row_ins_check_foreign_constraint (check_ref=0, foreign=0x616000058f08, table=0x618000045d08, entry=0x61600005ad28, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:1793
            #14 0x000055e3293378ee in row_upd_check_references_constraints (node=0x620000010bf8, pcur=0x611000071100, table=0x618000045d08, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:325
            #15 0x000055e3293321f1 in row_upd_del_mark_clust_rec (node=0x620000010bf8, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, referenced=1, foreign=false, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:2996
            #16 0x000055e32933009d in row_upd_clust_step (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3157
            #17 0x000055e32932ab65 in row_upd (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286
            #18 0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432
            #19 0x000055e329229c01 in row_update_for_mysql (prebuilt=0x620000010108) at ../storage/innobase/row/row0mysql.cc:1825
            #20 0x000055e328e52d64 in ha_innobase::delete_row (this=0x61c0000628a8, record=0x6190000d93b8 "\377d") at ../storage/innobase/handler/ha_innodb.cc:9059
            #21 0x000055e328759cba in handler::ha_delete_row (this=0x61c0000628a8, buf=0x6190000d93b8 "\377d") at ../sql/handler.cc:6168
            #22 0x000055e328ca6f07 in mysql_delete (thd=0x62a0000ba208, table_list=0x62b000000340, conds=0x62b000000b30, order_list=0x62a0000be7a0, limit=18446744073709551615, options=0, result=0x0) at ../sql/sql_delete.cc:583
            #23 0x000055e327e6e16b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:4362
            #24 0x000055e327e58ce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "DELETE FROM parent WHERE ID=100", length=31, parser_state=0x7fd54343eb20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733
            #25 0x000055e327e4a6c6 in dispatch_command (command=COM_QUERY, thd=0x62a0000ba208, packet=0x629000136209 "DELETE FROM parent WHERE ID=100", packet_length=31, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:1823
            #26 0x000055e327e53e39 in do_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:1377
            #27 0x000055e328352495 in do_handle_one_connection (connect=0x6080000014a8) at ../sql/sql_connect.cc:1336
            #28 0x000055e328351b44 in handle_one_connection (arg=0x6080000014a8) at ../sql/sql_connect.cc:1241
            #29 0x000055e329eb4e92 in pfs_spawn_thread (arg=0x615000007888) at ../storage/perfschema/pfs.cc:1869
            #30 0x00007fd55f2d93e9 in start_thread () from /usr/lib/libpthread.so.0
            #31 0x00007fd55e93c293 in clone () from /usr/lib/libc.so.6
            

            if is entered.

            It turned out that this happens due to different values stored in update->n_fields, and the behavior was different even much earlier, in row_upd_store_v_row called from row_upd_clust_step

            GOOD

            Thread 2 hit Breakpoint 23, row_upd_store_v_row (node=0x6210000a5d70, update=0x6210000a5e90, thd=0x62a0000ba208, mysql_table=0x61e00003cc88) at ../storage/innobase/row/row0upd.cc:2147
            2147				if (i >= n_upd) {
            (gdb) bt
            #0  row_upd_store_v_row (node=0x6210000a5d70, update=0x6210000a5e90, thd=0x62a0000ba208, mysql_table=0x61e00003cc88) at ../storage/innobase/row/row0upd.cc:2147
            #1  0x0000559ba088b628 in row_upd_store_row (node=0x6210000a5d70, thd=0x62a0000ba208, mysql_table=0x61e00003cc88) at ../storage/innobase/row/row0upd.cc:2240
            #2  0x0000559ba0887478 in row_upd_clust_step (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3190
            #3  0x0000559ba0881b65 in row_upd (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3286
            #4  0x0000559ba0880eb1 in row_upd_step (thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3432
            #5  0x0000559ba0780c01 in row_update_for_mysql (prebuilt=0x6210000a5188) at ../storage/innobase/row/row0mysql.cc:1825
            #6  0x0000559ba03a53bc in ha_innobase::update_row (this=0x61c0000638a8, old_row=0x6190000da2d0 "\371\363\340\001", new_row=0x6190000da2b8 "\373\363\340\001") at ../storage/innobase/handler/ha_innodb.cc:8943
            #7  0x0000559b9fcb023c in handler::ha_update_row (this=0x61c0000638a8, old_data=0x6190000da2d0 "\371\363\340\001", new_data=0x6190000da2b8 "\373\363\340\001") at ../sql/handler.cc:6140
            #8  0x0000559b9f74a156 in mysql_update (thd=0x62a0000ba208, table_list=0x62b000000370, fields=..., values=..., conds=0x62b000000d60, order_num=0, order=0x0, limit=18446744073709551615, handle_duplicates=DUP_ERROR, ignore=false, found_return=0x7f5da5d4e5a0, updated_return=0x7f5da5d4e5c0) at ../sql/sql_update.cc:817
            #9  0x0000559b9f3c0e4b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:3998
            #10 0x0000559b9f3afce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "UPDATE child set ParentID= NULL WHERE ParentID = 100", length=52, parser_state=0x7f5da5d50b20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733
            #11 0x0000559b9f3a16c6 in dispatch_command (command=COM_QUERY, thd=0x62a0000ba208, packet=0x629000136209 "UPDATE child set ParentID= NULL WHERE ParentID = 100", packet_length=52, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:1823
            #12 0x0000559b9f3aae39 in do_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:1377
            #13 0x0000559b9f8a9495 in do_handle_one_connection (connect=0x6080000014a8) at ../sql/sql_connect.cc:1336
            #14 0x0000559b9f8a8b44 in handle_one_connection (arg=0x6080000014a8) at ../sql/sql_connect.cc:1241
            #15 0x0000559ba140be92 in pfs_spawn_thread (arg=0x615000007888) at ../storage/perfschema/pfs.cc:1869
            #16 0x00007f5dc1beb3e9 in start_thread () from /usr/lib/libpthread.so.0
            #17 0x00007f5dc124e293 in clone () from /usr/lib/libc.so.6
            (gdb) p n_upd
            $1 = 1
            

            n_upd equals 1 (only one field is updated)

            BAD:

            Thread 2 hit Breakpoint 23, row_upd_store_v_row (node=0x61600005b008, update=0x61a00002d108, thd=0x62a0000ba208, mysql_table=0x0) at ../storage/innobase/row/row0upd.cc:2147
            2147				if (i >= n_upd) {
            (gdb) bt
            #0  row_upd_store_v_row (node=0x61600005b008, update=0x61a00002d108, thd=0x62a0000ba208, mysql_table=0x0) at ../storage/innobase/row/row0upd.cc:2147
            #1  0x000055e329334628 in row_upd_store_row (node=0x61600005b008, thd=0x62a0000ba208, mysql_table=0x0) at ../storage/innobase/row/row0upd.cc:2240
            #2  0x000055e329330478 in row_upd_clust_step (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3190
            #3  0x000055e32932ab65 in row_upd (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286
            #4  0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432
            #5  0x000055e32922d564 in row_update_cascade_for_mysql (thr=0x6240001dc188, node=0x61600005b008, table=0x618000046908) at ../storage/innobase/row/row0mysql.cc:2109
            #6  0x000055e3291bce29 in row_ins_foreign_check_on_constraint (thr=0x6240001dc188, foreign=0x616000058f08, pcur=0x7fd543432f80, entry=0x61600005ad28, mtr=0x7fd5434330c0) at ../storage/innobase/row/row0ins.cc:1404
            #7  0x000055e3291b7aa9 in row_ins_check_foreign_constraint (check_ref=0, foreign=0x616000058f08, table=0x618000045d08, entry=0x61600005ad28, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:1793
            #8  0x000055e3293378ee in row_upd_check_references_constraints (node=0x620000010bf8, pcur=0x611000071100, table=0x618000045d08, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:325
            #9  0x000055e3293321f1 in row_upd_del_mark_clust_rec (node=0x620000010bf8, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, referenced=1, foreign=false, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:2996
            #10 0x000055e32933009d in row_upd_clust_step (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3157
            #11 0x000055e32932ab65 in row_upd (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286
            #12 0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432
            #13 0x000055e329229c01 in row_update_for_mysql (prebuilt=0x620000010108) at ../storage/innobase/row/row0mysql.cc:1825
            #14 0x000055e328e52d64 in ha_innobase::delete_row (this=0x61c0000628a8, record=0x6190000d93b8 "\377d") at ../storage/innobase/handler/ha_innodb.cc:9059
            (gdb) p n_upd
            $1 = 2
            

            n_upd equals 2 (two fields are updated)

            This is right, we only update ParentID, and Flag should remain unchanged, but in ON DELETE SET NULL case it is also chaned (to NULL). I could have guessed earlier when I have seen NULL returning from b-tree, but it became clear only at the following point, wehere update->n_fields is set up last time, in row_ins_foreign_fill_virtual which fills an update vector for cascade cases:

            BAD:

            Thread 2 hit Breakpoint 25, row_ins_foreign_fill_virtual (cascade=0x61600005b008, rec=0x7fd555c7407e "", index=0x617000043708, node=0x620000010bf8, foreign=0x616000058f08) at ../storage/innobase/row/row0ins.cc:948
            948		update->n_fields += n_v_fld;
            (gdb) bt
            #0  row_ins_foreign_fill_virtual (cascade=0x61600005b008, rec=0x7fd555c7407e "", index=0x617000043708, node=0x620000010bf8, foreign=0x616000058f08) at ../storage/innobase/row/row0ins.cc:948
            #1  0x000055e3291bc2b9 in row_ins_foreign_check_on_constraint (thr=0x6240001dc188, foreign=0x616000058f08, pcur=0x7fd543432f80, entry=0x61600005ad28, mtr=0x7fd5434330c0) at ../storage/innobase/row/row0ins.cc:1300
            #2  0x000055e3291b7aa9 in row_ins_check_foreign_constraint (check_ref=0, foreign=0x616000058f08, table=0x618000045d08, entry=0x61600005ad28, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:1793
            #3  0x000055e3293378ee in row_upd_check_references_constraints (node=0x620000010bf8, pcur=0x611000071100, table=0x618000045d08, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:325
            #4  0x000055e3293321f1 in row_upd_del_mark_clust_rec (node=0x620000010bf8, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, referenced=1, foreign=false, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:2996
            #5  0x000055e32933009d in row_upd_clust_step (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3157
            #6  0x000055e32932ab65 in row_upd (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286
            #7  0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432
            #8  0x000055e329229c01 in row_update_for_mysql (prebuilt=0x620000010108) at ../storage/innobase/row/row0mysql.cc:1825
            #9  0x000055e328e52d64 in ha_innobase::delete_row (this=0x61c0000628a8, record=0x6190000d93b8 "\377d") at ../storage/innobase/handler/ha_innodb.cc:9059
            #10 0x000055e328759cba in handler::ha_delete_row (this=0x61c0000628a8, buf=0x6190000d93b8 "\377d") at ../sql/handler.cc:6168
            #11 0x000055e328ca6f07 in mysql_delete (thd=0x62a0000ba208, table_list=0x62b000000340, conds=0x62b000000b30, order_list=0x62a0000be7a0, limit=18446744073709551615, options=0, result=0x0) at ../sql/sql_delete.cc:583
            #12 0x000055e327e6e16b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:4362
            #13 0x000055e327e58ce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "DELETE FROM parent WHERE ID=100", length=31, parser_state=0x7fd54343eb20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733
            #14 0x000055e327e4a6c6 in dispatch_command (command=COM_QUERY, thd=0x62a0000ba208, packet=0x629000136209 "DELETE FROM parent WHERE ID=100", packet_length=31, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:1823
            (gdb) p n_v_fld
            $2 = 1
            

            update->n_fields, the number of fields changed, gets incremented bu a total number of virtual fields in table. Then it can be seen, again in row_ins_foreign_fill_virtual, that all the virtual fields sharing the index of the FOREIGN KEY are set to NULL, which is incorrect.

            Actually, the total number of indexed virtual fields in the table could be more than a number of virtual columns in FK index, and that can be another bug.

            nikitamalyavin Nikita Malyavin added a comment - - edited Analysis report First of all I was successful at reducing the test case to ~25 lines. It turned out that one record for each table is enough: --source include/have_innodb.inc   set default_storage_engine=innodb;   CREATE TABLE parent ( ID int unsigned NOT NULL , PRIMARY KEY (ID) );   CREATE TABLE child ( ID int unsigned NOT NULL , ParentID int unsigned NULL , Value int unsigned NOT NULL DEFAULT 0xbababebe, Flag int unsigned AS (Value) VIRTUAL, PRIMARY KEY (ID), KEY (ParentID,Flag), FOREIGN KEY (ParentID) REFERENCES parent (ID) ON DELETE SET NULL ON UPDATE CASCADE );   INSERT INTO parent (ID) VALUES (100); INSERT INTO child (ID,ParentID,Value) VALUES (123123,100,1); # UPDATE child set ParentID= NULL WHERE ParentID = 100; DELETE FROM parent WHERE ID=100; select * from child; INSERT INTO parent (ID) VALUES (100); UPDATE child SET ParentID=100 WHERE ID=123123; This is the minimal test case to fail. To analyze the problem I used good/bad strategy. First I tried to compare the behaviors without the virtual column, by substituting Flag type with INT UNSIGNED DEFAULT (123) . Tracing the data changes has only shown that the value returned from the b-tree index contains Flag=NULL in BAD case (so the match didn't happen, and therefore the assertion has failed) and Flag=123 in GOOD case. Second approach was to compare the cascade SET NULL update behavior with UPDATE child SET Parent=NULL and to see what the difference is there. Hopefully, both functions make an update with row_upd call. I have placed the breakpoints in some key places when data transitions happen. We could expect that both cases would behave identically during update, and that gets confirmed by stack traces. GOOD: #0 rec_copy (buf=0x611000071188, rec=0x7f5db859007e "", offsets=0x7f5da5d45d40) at ../storage/innobase/include/rem0rec.ic:1563 #1 0x0000559ba07ef1cd in row_build_low (type=1, index=0x617000043708, rec=0x7f5db859007e "", offsets=0x7f5da5d45d40, col_table=0x0, add_cols=0x0, add_v=0x0, col_map=0x0, ext=0x6210000a5e50, heap=0x611000071100) at ../storage/innobase/row/row0row.cc:426 #2 0x0000559ba07eeb8a in row_build (type=1, index=0x617000043708, rec=0x7f5db859007e "", offsets=0x7f5da5d45d40, col_table=0x0, add_cols=0x0, col_map=0x0, ext=0x6210000a5e50, heap=0x611000071100) at ../storage/innobase/row/row0row.cc:602 #3 0x0000559ba088b457 in row_upd_store_row (node=0x6210000a5d70, thd=0x62a0000ba208, mysql_table=0x61e00003cc88) at ../storage/innobase/row/row0upd.cc:2236 #4 0x0000559ba0887478 in row_upd_clust_step (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3190 #5 0x0000559ba0881b65 in row_upd (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3286 #6 0x0000559ba0880eb1 in row_upd_step (thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3432 #7 0x0000559ba0780c01 in row_update_for_mysql (prebuilt=0x6210000a5188) at ../storage/innobase/row/row0mysql.cc:1825 #8 0x0000559ba03a53bc in ha_innobase::update_row (this=0x61c0000638a8, old_row=0x6190000da2d0 "\371\363\340\001", new_row=0x6190000da2b8 "\373\363\340\001") at ../storage/innobase/handler/ha_innodb.cc:8943 #9 0x0000559b9fcb023c in handler::ha_update_row (this=0x61c0000638a8, old_data=0x6190000da2d0 "\371\363\340\001", new_data=0x6190000da2b8 "\373\363\340\001") at ../sql/handler.cc:6140 #10 0x0000559b9f74a156 in mysql_update (thd=0x62a0000ba208, table_list=0x62b000000370, fields=..., values=..., conds=0x62b000000d60, order_num=0, order=0x0, limit=18446744073709551615, handle_duplicates=DUP_ERROR, ignore=false, found_return=0x7f5da5d4e5a0, updated_return=0x7f5da5d4e5c0) at ../sql/sql_update.cc:817 #11 0x0000559b9f3c0e4b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:3998 #12 0x0000559b9f3afce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "UPDATE child set ParentID= NULL WHERE ParentID = 100", length=52, parser_state=0x7f5da5d50b20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733 BAD: #0 rec_copy (buf=0x61600005b410, rec=0x7fd555c7407e "", offsets=0x7fd543430b80) at ../storage/innobase/include/rem0rec.ic:1563 #1 0x000055e3292981cd in row_build_low (type=1, index=0x617000043708, rec=0x7fd555c7407e "", offsets=0x7fd543430b80, col_table=0x0, add_cols=0x0, add_v=0x0, col_map=0x0, ext=0x61600005b0e8, heap=0x611000071380) at ../storage/innobase/row/row0row.cc:426 #2 0x000055e329297b8a in row_build (type=1, index=0x617000043708, rec=0x7fd555c7407e "", offsets=0x7fd543430b80, col_table=0x0, add_cols=0x0, col_map=0x0, ext=0x61600005b0e8, heap=0x611000071380) at ../storage/innobase/row/row0row.cc:602 #3 0x000055e329334457 in row_upd_store_row (node=0x61600005b008, thd=0x62a0000ba208, mysql_table=0x0) at ../storage/innobase/row/row0upd.cc:2236 #4 0x000055e329330478 in row_upd_clust_step (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3190 #5 0x000055e32932ab65 in row_upd (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286 #6 0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432 #7 0x000055e32922d564 in row_update_cascade_for_mysql (thr=0x6240001dc188, node=0x61600005b008, table=0x618000046908) at ../storage/innobase/row/row0mysql.cc:2109 #8 0x000055e3291bce29 in row_ins_foreign_check_on_constraint (thr=0x6240001dc188, foreign=0x616000058f08, pcur=0x7fd543432f80, entry=0x61600005ad28, mtr=0x7fd5434330c0) at ../storage/innobase/row/row0ins.cc:1404 #9 0x000055e3291b7aa9 in row_ins_check_foreign_constraint (check_ref=0, foreign=0x616000058f08, table=0x618000045d08, entry=0x61600005ad28, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:1793 #10 0x000055e3293378ee in row_upd_check_references_constraints (node=0x620000010bf8, pcur=0x611000071100, table=0x618000045d08, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:325 #11 0x000055e3293321f1 in row_upd_del_mark_clust_rec (node=0x620000010bf8, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, referenced=1, foreign=false, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:2996 #12 0x000055e32933009d in row_upd_clust_step (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3157 #13 0x000055e32932ab65 in row_upd (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286 #14 0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432 #15 0x000055e329229c01 in row_update_for_mysql (prebuilt=0x620000010108) at ../storage/innobase/row/row0mysql.cc:1825 #16 0x000055e328e52d64 in ha_innobase::delete_row (this=0x61c0000628a8, record=0x6190000d93b8 "\377d") at ../storage/innobase/handler/ha_innodb.cc:9059 #17 0x000055e328759cba in handler::ha_delete_row (this=0x61c0000628a8, buf=0x6190000d93b8 "\377d") at ../sql/handler.cc:6168 #18 0x000055e328ca6f07 in mysql_delete (thd=0x62a0000ba208, table_list=0x62b000000340, conds=0x62b000000b30, order_list=0x62a0000be7a0, limit=18446744073709551615, options=0, result=0x0) at ../sql/sql_delete.cc:583 #19 0x000055e327e6e16b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:4362 #20 0x000055e327e58ce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "DELETE FROM parent WHERE ID=100", length=31, parser_state=0x7fd54343eb20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733 We can see here, that top 5 frames are identical, and that is expected to be persistent during the whole functinon execution (considering it is designed well). I was expecting the difference in row_upd_sec_index_entry , since it is the function where the secondary index update happens. The first difference I found was in rec_convert_dtuple_to_rec_comp record-tuple comparison function. GOOD: #0 rec_convert_dtuple_to_rec_comp (rec=0x6190000dc10e "\276\276\276\276"..., index=0x617000044188, fields=0x6190000dbc40, n_fields=3, status=0, temp=false) at ../storage/innobase/rem/rem0rec.cc:1262 #1 0x0000559ba06b76be in rec_convert_dtuple_to_rec_new (buf=0x6190000dc108 "\001\276", index=0x617000044188, dtuple=0x6190000dbc08) at ../storage/innobase/rem/rem0rec.cc:1338 #2 0x0000559ba06b73ce in rec_convert_dtuple_to_rec (buf=0x6190000dc108 "\001\276", index=0x617000044188, dtuple=0x6190000dbc08, n_ext=0) at ../storage/innobase/rem/rem0rec.cc:1370 #3 0x0000559ba0a71140 in page_cur_tuple_insert (cursor=0x7f5da5d44328, tuple=0x6190000dbc08, index=0x617000044188, offsets=0x7f5da5d44c30, heap=0x7f5da5d442c0, n_ext=0, mtr=0x7f5da5d44400, use_cache=false) at ../storage/innobase/include/page0cur.ic:280 #4 0x0000559ba0a6ebd2 in btr_cur_optimistic_insert (flags=0, cursor=0x7f5da5d44320, offsets=0x7f5da5d44c30, heap=0x7f5da5d442c0, entry=0x6190000dbc08, rec=0x7f5da5d45420, big_rec=0x7f5da5d45440, n_ext=0, thr=0x6250000f0188, mtr=0x7f5da5d44400) at ../storage/innobase/btr/btr0cur.cc:3237 #5 0x0000559ba071c25f in row_ins_sec_index_entry_low (flags=0, mode=2, index=0x617000044188, offsets_heap=0x6190000dc080, heap=0x6190000dc580, entry=0x6190000dbc08, trx_id=0, thr=0x6250000f0188) at ../storage/innobase/row/row0ins.cc:3029 #6 0x0000559ba0720496 in row_ins_sec_index_entry (index=0x617000044188, entry=0x6190000dbc08, thr=0x6250000f0188) at ../storage/innobase/row/row0ins.cc:3203 #7 0x0000559ba0895093 in row_upd_sec_index_entry (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:2526 #8 0x0000559ba0887c94 in row_upd_sec_step (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:2553 #9 0x0000559ba088220f in row_upd (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3315 #10 0x0000559ba0880eb1 in row_upd_step (thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3432 #11 0x0000559ba0780c01 in row_update_for_mysql (prebuilt=0x6210000a5188) at ../storage/innobase/row/row0mysql.cc:1825 #12 0x0000559ba03a53bc in ha_innobase::update_row (this=0x61c0000638a8, old_row=0x6190000da2d0 "\371\363\340\001", new_row=0x6190000da2b8 "\373\363\340\001") at ../storage/innobase/handler/ha_innodb.cc:8943 #13 0x0000559b9fcb023c in handler::ha_update_row (this=0x61c0000638a8, old_data=0x6190000da2d0 "\371\363\340\001", new_data=0x6190000da2b8 "\373\363\340\001") at ../sql/handler.cc:6140 #14 0x0000559b9f74a156 in mysql_update (thd=0x62a0000ba208, table_list=0x62b000000370, fields=..., values=..., conds=0x62b000000d60, order_num=0, order=0x0, limit=18446744073709551615, handle_duplicates=DUP_ERROR, ignore=false, found_return=0x7f5da5d4e5a0, updated_return=0x7f5da5d4e5c0) at ../sql/sql_update.cc:817 #15 0x0000559b9f3c0e4b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:3998 #16 0x0000559b9f3afce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "UPDATE child set ParentID= NULL WHERE ParentID = 100", length=52, parser_state=0x7f5da5d50b20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733 if (dfield_is_null(field)) entry is bypassed BAD #0 rec_convert_dtuple_to_rec_comp (rec=0x6190000dc10e "\276\276\276"..., index=0x617000044188, fields=0x6190000dbc40, n_fields=3, status=0, temp=false) at ../storage/innobase/rem/rem0rec.cc:1257 #1 0x000055e3291606be in rec_convert_dtuple_to_rec_new (buf=0x6190000dc108 "\001\276", index=0x617000044188, dtuple=0x6190000dbc08) at ../storage/innobase/rem/rem0rec.cc:1338 #2 0x000055e3291603ce in rec_convert_dtuple_to_rec (buf=0x6190000dc108 "\001\276", index=0x617000044188, dtuple=0x6190000dbc08, n_ext=0) at ../storage/innobase/rem/rem0rec.cc:1370 #3 0x000055e32951a140 in page_cur_tuple_insert (cursor=0x7fd54342f168, tuple=0x6190000dbc08, index=0x617000044188, offsets=0x7fd54342fa70, heap=0x7fd54342f100, n_ext=0, mtr=0x7fd54342f240, use_cache=false) at ../storage/innobase/include/page0cur.ic:280 #4 0x000055e329517bd2 in btr_cur_optimistic_insert (flags=0, cursor=0x7fd54342f160, offsets=0x7fd54342fa70, heap=0x7fd54342f100, entry=0x6190000dbc08, rec=0x7fd543430260, big_rec=0x7fd543430280, n_ext=0, thr=0x6240001dc188, mtr=0x7fd54342f240) at ../storage/innobase/btr/btr0cur.cc:3237 #5 0x000055e3291c525f in row_ins_sec_index_entry_low (flags=0, mode=2, index=0x617000044188, offsets_heap=0x6190000dc080, heap=0x6190000dc580, entry=0x6190000dbc08, trx_id=0, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:3029 #6 0x000055e3291c9496 in row_ins_sec_index_entry (index=0x617000044188, entry=0x6190000dbc08, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:3203 #7 0x000055e32933e093 in row_upd_sec_index_entry (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:2526 #8 0x000055e329330c94 in row_upd_sec_step (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:2553 #9 0x000055e32932b20f in row_upd (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3315 #10 0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432 #11 0x000055e32922d564 in row_update_cascade_for_mysql (thr=0x6240001dc188, node=0x61600005b008, table=0x618000046908) at ../storage/innobase/row/row0mysql.cc:2109 #12 0x000055e3291bce29 in row_ins_foreign_check_on_constraint (thr=0x6240001dc188, foreign=0x616000058f08, pcur=0x7fd543432f80, entry=0x61600005ad28, mtr=0x7fd5434330c0) at ../storage/innobase/row/row0ins.cc:1404 #13 0x000055e3291b7aa9 in row_ins_check_foreign_constraint (check_ref=0, foreign=0x616000058f08, table=0x618000045d08, entry=0x61600005ad28, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:1793 #14 0x000055e3293378ee in row_upd_check_references_constraints (node=0x620000010bf8, pcur=0x611000071100, table=0x618000045d08, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:325 #15 0x000055e3293321f1 in row_upd_del_mark_clust_rec (node=0x620000010bf8, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, referenced=1, foreign=false, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:2996 #16 0x000055e32933009d in row_upd_clust_step (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3157 #17 0x000055e32932ab65 in row_upd (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286 #18 0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432 #19 0x000055e329229c01 in row_update_for_mysql (prebuilt=0x620000010108) at ../storage/innobase/row/row0mysql.cc:1825 #20 0x000055e328e52d64 in ha_innobase::delete_row (this=0x61c0000628a8, record=0x6190000d93b8 "\377d") at ../storage/innobase/handler/ha_innodb.cc:9059 #21 0x000055e328759cba in handler::ha_delete_row (this=0x61c0000628a8, buf=0x6190000d93b8 "\377d") at ../sql/handler.cc:6168 #22 0x000055e328ca6f07 in mysql_delete (thd=0x62a0000ba208, table_list=0x62b000000340, conds=0x62b000000b30, order_list=0x62a0000be7a0, limit=18446744073709551615, options=0, result=0x0) at ../sql/sql_delete.cc:583 #23 0x000055e327e6e16b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:4362 #24 0x000055e327e58ce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "DELETE FROM parent WHERE ID=100", length=31, parser_state=0x7fd54343eb20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733 #25 0x000055e327e4a6c6 in dispatch_command (command=COM_QUERY, thd=0x62a0000ba208, packet=0x629000136209 "DELETE FROM parent WHERE ID=100", packet_length=31, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:1823 #26 0x000055e327e53e39 in do_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:1377 #27 0x000055e328352495 in do_handle_one_connection (connect=0x6080000014a8) at ../sql/sql_connect.cc:1336 #28 0x000055e328351b44 in handle_one_connection (arg=0x6080000014a8) at ../sql/sql_connect.cc:1241 #29 0x000055e329eb4e92 in pfs_spawn_thread (arg=0x615000007888) at ../storage/perfschema/pfs.cc:1869 #30 0x00007fd55f2d93e9 in start_thread () from /usr/lib/libpthread.so.0 #31 0x00007fd55e93c293 in clone () from /usr/lib/libc.so.6 if is entered. It turned out that this happens due to different values stored in update->n_fields , and the behavior was different even much earlier, in row_upd_store_v_row called from row_upd_clust_step GOOD Thread 2 hit Breakpoint 23, row_upd_store_v_row (node=0x6210000a5d70, update=0x6210000a5e90, thd=0x62a0000ba208, mysql_table=0x61e00003cc88) at ../storage/innobase/row/row0upd.cc:2147 2147 if (i >= n_upd) { (gdb) bt #0 row_upd_store_v_row (node=0x6210000a5d70, update=0x6210000a5e90, thd=0x62a0000ba208, mysql_table=0x61e00003cc88) at ../storage/innobase/row/row0upd.cc:2147 #1 0x0000559ba088b628 in row_upd_store_row (node=0x6210000a5d70, thd=0x62a0000ba208, mysql_table=0x61e00003cc88) at ../storage/innobase/row/row0upd.cc:2240 #2 0x0000559ba0887478 in row_upd_clust_step (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3190 #3 0x0000559ba0881b65 in row_upd (node=0x6210000a5d70, thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3286 #4 0x0000559ba0880eb1 in row_upd_step (thr=0x6250000f0188) at ../storage/innobase/row/row0upd.cc:3432 #5 0x0000559ba0780c01 in row_update_for_mysql (prebuilt=0x6210000a5188) at ../storage/innobase/row/row0mysql.cc:1825 #6 0x0000559ba03a53bc in ha_innobase::update_row (this=0x61c0000638a8, old_row=0x6190000da2d0 "\371\363\340\001", new_row=0x6190000da2b8 "\373\363\340\001") at ../storage/innobase/handler/ha_innodb.cc:8943 #7 0x0000559b9fcb023c in handler::ha_update_row (this=0x61c0000638a8, old_data=0x6190000da2d0 "\371\363\340\001", new_data=0x6190000da2b8 "\373\363\340\001") at ../sql/handler.cc:6140 #8 0x0000559b9f74a156 in mysql_update (thd=0x62a0000ba208, table_list=0x62b000000370, fields=..., values=..., conds=0x62b000000d60, order_num=0, order=0x0, limit=18446744073709551615, handle_duplicates=DUP_ERROR, ignore=false, found_return=0x7f5da5d4e5a0, updated_return=0x7f5da5d4e5c0) at ../sql/sql_update.cc:817 #9 0x0000559b9f3c0e4b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:3998 #10 0x0000559b9f3afce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "UPDATE child set ParentID= NULL WHERE ParentID = 100", length=52, parser_state=0x7f5da5d50b20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733 #11 0x0000559b9f3a16c6 in dispatch_command (command=COM_QUERY, thd=0x62a0000ba208, packet=0x629000136209 "UPDATE child set ParentID= NULL WHERE ParentID = 100", packet_length=52, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:1823 #12 0x0000559b9f3aae39 in do_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:1377 #13 0x0000559b9f8a9495 in do_handle_one_connection (connect=0x6080000014a8) at ../sql/sql_connect.cc:1336 #14 0x0000559b9f8a8b44 in handle_one_connection (arg=0x6080000014a8) at ../sql/sql_connect.cc:1241 #15 0x0000559ba140be92 in pfs_spawn_thread (arg=0x615000007888) at ../storage/perfschema/pfs.cc:1869 #16 0x00007f5dc1beb3e9 in start_thread () from /usr/lib/libpthread.so.0 #17 0x00007f5dc124e293 in clone () from /usr/lib/libc.so.6 (gdb) p n_upd $1 = 1 n_upd equals 1 (only one field is updated) BAD: Thread 2 hit Breakpoint 23, row_upd_store_v_row (node=0x61600005b008, update=0x61a00002d108, thd=0x62a0000ba208, mysql_table=0x0) at ../storage/innobase/row/row0upd.cc:2147 2147 if (i >= n_upd) { (gdb) bt #0 row_upd_store_v_row (node=0x61600005b008, update=0x61a00002d108, thd=0x62a0000ba208, mysql_table=0x0) at ../storage/innobase/row/row0upd.cc:2147 #1 0x000055e329334628 in row_upd_store_row (node=0x61600005b008, thd=0x62a0000ba208, mysql_table=0x0) at ../storage/innobase/row/row0upd.cc:2240 #2 0x000055e329330478 in row_upd_clust_step (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3190 #3 0x000055e32932ab65 in row_upd (node=0x61600005b008, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286 #4 0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432 #5 0x000055e32922d564 in row_update_cascade_for_mysql (thr=0x6240001dc188, node=0x61600005b008, table=0x618000046908) at ../storage/innobase/row/row0mysql.cc:2109 #6 0x000055e3291bce29 in row_ins_foreign_check_on_constraint (thr=0x6240001dc188, foreign=0x616000058f08, pcur=0x7fd543432f80, entry=0x61600005ad28, mtr=0x7fd5434330c0) at ../storage/innobase/row/row0ins.cc:1404 #7 0x000055e3291b7aa9 in row_ins_check_foreign_constraint (check_ref=0, foreign=0x616000058f08, table=0x618000045d08, entry=0x61600005ad28, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:1793 #8 0x000055e3293378ee in row_upd_check_references_constraints (node=0x620000010bf8, pcur=0x611000071100, table=0x618000045d08, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:325 #9 0x000055e3293321f1 in row_upd_del_mark_clust_rec (node=0x620000010bf8, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, referenced=1, foreign=false, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:2996 #10 0x000055e32933009d in row_upd_clust_step (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3157 #11 0x000055e32932ab65 in row_upd (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286 #12 0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432 #13 0x000055e329229c01 in row_update_for_mysql (prebuilt=0x620000010108) at ../storage/innobase/row/row0mysql.cc:1825 #14 0x000055e328e52d64 in ha_innobase::delete_row (this=0x61c0000628a8, record=0x6190000d93b8 "\377d") at ../storage/innobase/handler/ha_innodb.cc:9059 (gdb) p n_upd $1 = 2 n_upd equals 2 (two fields are updated) This is right, we only update ParentID, and Flag should remain unchanged, but in ON DELETE SET NULL case it is also chaned (to NULL). I could have guessed earlier when I have seen NULL returning from b-tree, but it became clear only at the following point, wehere update->n_fields is set up last time, in row_ins_foreign_fill_virtual which fills an update vector for cascade cases: BAD: Thread 2 hit Breakpoint 25, row_ins_foreign_fill_virtual (cascade=0x61600005b008, rec=0x7fd555c7407e "", index=0x617000043708, node=0x620000010bf8, foreign=0x616000058f08) at ../storage/innobase/row/row0ins.cc:948 948 update->n_fields += n_v_fld; (gdb) bt #0 row_ins_foreign_fill_virtual (cascade=0x61600005b008, rec=0x7fd555c7407e "", index=0x617000043708, node=0x620000010bf8, foreign=0x616000058f08) at ../storage/innobase/row/row0ins.cc:948 #1 0x000055e3291bc2b9 in row_ins_foreign_check_on_constraint (thr=0x6240001dc188, foreign=0x616000058f08, pcur=0x7fd543432f80, entry=0x61600005ad28, mtr=0x7fd5434330c0) at ../storage/innobase/row/row0ins.cc:1300 #2 0x000055e3291b7aa9 in row_ins_check_foreign_constraint (check_ref=0, foreign=0x616000058f08, table=0x618000045d08, entry=0x61600005ad28, thr=0x6240001dc188) at ../storage/innobase/row/row0ins.cc:1793 #3 0x000055e3293378ee in row_upd_check_references_constraints (node=0x620000010bf8, pcur=0x611000071100, table=0x618000045d08, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:325 #4 0x000055e3293321f1 in row_upd_del_mark_clust_rec (node=0x620000010bf8, index=0x617000042c88, offsets=0x7fd543434e30, thr=0x6240001dc188, referenced=1, foreign=false, mtr=0x7fd5434348c0) at ../storage/innobase/row/row0upd.cc:2996 #5 0x000055e32933009d in row_upd_clust_step (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3157 #6 0x000055e32932ab65 in row_upd (node=0x620000010bf8, thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3286 #7 0x000055e329329eb1 in row_upd_step (thr=0x6240001dc188) at ../storage/innobase/row/row0upd.cc:3432 #8 0x000055e329229c01 in row_update_for_mysql (prebuilt=0x620000010108) at ../storage/innobase/row/row0mysql.cc:1825 #9 0x000055e328e52d64 in ha_innobase::delete_row (this=0x61c0000628a8, record=0x6190000d93b8 "\377d") at ../storage/innobase/handler/ha_innodb.cc:9059 #10 0x000055e328759cba in handler::ha_delete_row (this=0x61c0000628a8, buf=0x6190000d93b8 "\377d") at ../sql/handler.cc:6168 #11 0x000055e328ca6f07 in mysql_delete (thd=0x62a0000ba208, table_list=0x62b000000340, conds=0x62b000000b30, order_list=0x62a0000be7a0, limit=18446744073709551615, options=0, result=0x0) at ../sql/sql_delete.cc:583 #12 0x000055e327e6e16b in mysql_execute_command (thd=0x62a0000ba208) at ../sql/sql_parse.cc:4362 #13 0x000055e327e58ce6 in mysql_parse (thd=0x62a0000ba208, rawbuf=0x62b000000228 "DELETE FROM parent WHERE ID=100", length=31, parser_state=0x7fd54343eb20, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:7733 #14 0x000055e327e4a6c6 in dispatch_command (command=COM_QUERY, thd=0x62a0000ba208, packet=0x629000136209 "DELETE FROM parent WHERE ID=100", packet_length=31, is_com_multi=false, is_next_command=false) at ../sql/sql_parse.cc:1823 (gdb) p n_v_fld $2 = 1 update->n_fields , the number of fields changed, gets incremented bu a total number of virtual fields in table. Then it can be seen, again in row_ins_foreign_fill_virtual , that all the virtual fields sharing the index of the FOREIGN KEY are set to NULL, which is incorrect. Actually, the total number of indexed virtual fields in the table could be more than a number of virtual columns in FK index, and that can be another bug.
            nikitamalyavin Nikita Malyavin added a comment - The fix was pushed to bb-10.2-nikita . Buildbot: https://buildbot.askmonty.org/buildbot/grid?category=main&branch=bb-10.2-nikita

            Note: the initial support for CASCADE/SET NULL was added here: https://github.com/mysql/mysql-server/commit/5ed18d823c4fad30b75ab4b68c7327c1b95821d3

            nikitamalyavin Nikita Malyavin added a comment - Note: the initial support for CASCADE/SET NULL was added here: https://github.com/mysql/mysql-server/commit/5ed18d823c4fad30b75ab4b68c7327c1b95821d3

            People

              thiru Thirunarayanan Balathandayuthapani
              Dean T Dean Trower
              Votes:
              0 Vote for this issue
              Watchers:
              6 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.