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

Assertion `!prebuilt->index->is_primary()' failed in row_search_idx_cond_check with rowid_filter upon concurrent access to table

Details

    • Bug
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Fixed
    • 10.4(EOL)
    • 10.4.12
    • Optimizer
    • None

    Description

      Note: The test case is non-deterministic. Run in MTR with --repeat=N. On my box it fails within a few attempts and --repeat=10 is enough, but it can vary on different machines and builds.

      --source include/have_innodb.inc
       
      SET @innodb_stats_persistent.save= @@global.innodb_stats_persistent;
      SET GLOBAL innodb_stats_persistent= on;
       
      CREATE TABLE t1 (
          pk int auto_increment,
          a int,
          b int,
          primary key (pk),
          key (a),
          key (b)
      ) ENGINE=InnoDB;
      INSERT INTO t1 (a,b) VALUES
      (0,0),(0,9),(0,NULL),(1,2),(4,0),(2,9),(1,0),(NULL,0),(5,NULL),(5,1),
      (0,7),(NULL,5),(NULL,0),(2,1),(2,5),(6,NULL),(0,NULL),(NULL,8),(8,5),
      (2,NULL),(2,3),(NULL,8),(NULL,6),(1,1),(5,1),(NULL,5),(4,4),(2,4),
      (2,5),(1,9),(NULL,0),(3,7),(0,4),(2,8),(NULL,2),(1,4),(NULL,1),(NULL,7),
      (6,6),(NULL,0),(NULL,5),(NULL,2),(8,2),(NULL,NULL),(8,NULL),(0,1),(0,7);
       
      --connect (con1,localhost,root,,test)
      --send
          SELECT * FROM t1 WHERE ( a BETWEEN 9 AND 10 OR a IS NULL ) AND ( b BETWEEN 9 AND 10 OR b = 155 ) ORDER BY pk;
       
      --connection default
      SELECT * FROM t1 LIMIT 0;
       
      --connection con1
      --reap
       
      # Cleanup
      --disconnect con1
      --connection default
      DROP TABLE t1;
      SET GLOBAL innodb_stats_persistent= @innodb_stats_persistent.save;
      

      10.4 d2697dfb

      mysqld: /data/src/10.4/storage/innobase/row/row0sel.cc:3942: ICP_RESULT row_search_idx_cond_check(byte*, row_prebuilt_t*, const rec_t*, const offset_t*): Assertion `!prebuilt->index->is_primary()' failed.
      200109  1:22:46 [ERROR] mysqld got signal 6 ;
       
      #7  0x00007f2842f60f12 in __GI___assert_fail (assertion=0x55f96d8cdc08 "!prebuilt->index->is_primary()", file=0x55f96d8ccb40 "/data/src/10.4/storage/innobase/row/row0sel.cc", line=3942, function=0x55f96d8d0c80 <row_search_idx_cond_check(unsigned char*, row_prebuilt_t*, unsigned char const*, unsigned short const*)::__PRETTY_FUNCTION__> "ICP_RESULT row_search_idx_cond_check(byte*, row_prebuilt_t*, const rec_t*, const offset_t*)") at assert.c:101
      #8  0x000055f96d0c53c6 in row_search_idx_cond_check (mysql_rec=0x7f27f0019d70 "\211\001", prebuilt=0x7f27f001ae18, rec=0x7f283caf807e "\200", offsets=0x7f283c2e3ea0) at /data/src/10.4/storage/innobase/row/row0sel.cc:3942
      #9  0x000055f96d0c9396 in row_search_mvcc (buf=0x7f27f0019d70 "\211\001", mode=PAGE_CUR_G, prebuilt=0x7f27f001ae18, match_mode=0, direction=0) at /data/src/10.4/storage/innobase/row/row0sel.cc:5257
      #10 0x000055f96ced9822 in ha_innobase::index_read (this=0x7f27f001a1c8, buf=0x7f27f0019d70 "\211\001", key_ptr=0x0, key_len=0, find_flag=HA_READ_AFTER_KEY) at /data/src/10.4/storage/innobase/handler/ha_innodb.cc:9296
      #11 0x000055f96ceda82a in ha_innobase::index_first (this=0x7f27f001a1c8, buf=0x7f27f0019d70 "\211\001") at /data/src/10.4/storage/innobase/handler/ha_innodb.cc:9669
      #12 0x000055f96cc8f77f in handler::ha_index_first (this=0x7f27f001a1c8, buf=0x7f27f0019d70 "\211\001") at /data/src/10.4/sql/handler.cc:2975
      #13 0x000055f96c9ab905 in join_read_first (tab=0x7f27f0016fa0) at /data/src/10.4/sql/sql_select.cc:21261
      #14 0x000055f96c9a905b in sub_select (join=0x7f27f00146e0, join_tab=0x7f27f0016fa0, end_of_records=false) at /data/src/10.4/sql/sql_select.cc:20252
      #15 0x000055f96c9a854c in do_select (join=0x7f27f00146e0, procedure=0x0) at /data/src/10.4/sql/sql_select.cc:19793
      #16 0x000055f96c97d72f in JOIN::exec_inner (this=0x7f27f00146e0) at /data/src/10.4/sql/sql_select.cc:4452
      #17 0x000055f96c97c86c in JOIN::exec (this=0x7f27f00146e0) at /data/src/10.4/sql/sql_select.cc:4234
      #18 0x000055f96c97df81 in mysql_select (thd=0x7f27f0000af0, tables=0x7f27f00124d8, wild_num=1, fields=..., conds=0x7f27f0013af0, og_num=1, order=0x7f27f0014560, group=0x0, having=0x0, proc_param=0x0, select_options=2147748608, result=0x7f27f00146b8, unit=0x7f27f0004a18, select_lex=0x7f27f0011f18) at /data/src/10.4/sql/sql_select.cc:4666
      #19 0x000055f96c96db32 in handle_select (thd=0x7f27f0000af0, lex=0x7f27f0004958, result=0x7f27f00146b8, setup_tables_done_option=0) at /data/src/10.4/sql/sql_select.cc:420
      #20 0x000055f96c9342ab in execute_sqlcom_select (thd=0x7f27f0000af0, all_tables=0x7f27f00124d8) at /data/src/10.4/sql/sql_parse.cc:6360
      #21 0x000055f96c929959 in mysql_execute_command (thd=0x7f27f0000af0) at /data/src/10.4/sql/sql_parse.cc:3899
      #22 0x000055f96c9383b7 in mysql_parse (thd=0x7f27f0000af0, rawbuf=0x7f27f0011dd8 "SELECT * FROM t1 WHERE ( a BETWEEN 9 AND 10 OR a IS NULL ) AND ( b BETWEEN 9 AND 10 OR b = 155 ) ORDER BY pk", length=108, parser_state=0x7f283c2e6160, is_com_multi=false, is_next_command=false) at /data/src/10.4/sql/sql_parse.cc:7901
      #23 0x000055f96c92355c in dispatch_command (command=COM_QUERY, thd=0x7f27f0000af0, packet=0x7f27f00083a1 "", packet_length=108, is_com_multi=false, is_next_command=false) at /data/src/10.4/sql/sql_parse.cc:1842
      #24 0x000055f96c921be9 in do_command (thd=0x7f27f0000af0) at /data/src/10.4/sql/sql_parse.cc:1360
      #25 0x000055f96caaab5f in do_handle_one_connection (connect=0x55f96f26f8e0) at /data/src/10.4/sql/sql_connect.cc:1412
      #26 0x000055f96caaa8ae in handle_one_connection (arg=0x55f96f26f8e0) at /data/src/10.4/sql/sql_connect.cc:1316
      #27 0x000055f96d4b0e01 in pfs_spawn_thread (arg=0x55f96f1dc360) at /data/src/10.4/storage/perfschema/pfs.cc:1862
      #28 0x00007f2844ee94a4 in start_thread (arg=0x7f283c2e7700) at pthread_create.c:456
      #29 0x00007f284301dd0f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:97
      

      Notes:

      • Reproducible on 10.4 and 10.5.
      • Not reproducible with rowid_filter=off.
      • Couldn't reproduce without innodb_stats_persistent.
      • On the dataset above, ANALYZE makes the failure go away. I couldn't modify the test so that it would deterministically reproduce the failure with ANALYZE without concurrency, hopefully debugging will narrow down the problem and will allow to create such a data set.
      • The concurrent SELECT * FROM can be replaced by other statements accessing the table. I tried different kinds of SELECT, SHOW CREATE TABLE and ANALYZE, with all of them the failure was reproducible.
      • No crash on a non-debug build.

      Attachments

        Issue Links

          Activity

            1. The failure is easily reproducible with one run of the test case.
            2. If I execute ANALYZE TABLE t1 after the INSERT command the failure cannot be reproduced.
            3. Alternatively if I do not use the setting

            SET global innodb_stats_persistent=on;
            

            the failure cannot be reproduced.

            4. The cause of the problem can be easily seen if to execute

            EXPLAIN EXTENDED
            SELECT * FROM t1
              WHERE (a BETWEEN 9 AND 10 OR a IS NULL) AND (b BETWEEN 9 AND 10 OR b = 155)
            ORDER BY pk;
            

            instead of the corresponding SELECT query:

            EXPLAIN EXTENDED
            SELECT * FROM t1
            WHERE (a BETWEEN 9 AND 10 OR a IS NULL) AND (b BETWEEN 9 AND 10 OR b = 155)
            ORDER BY pk;
            id      select_type     table   type    possible_keys   key     key_len ref     rows    filtered        Extra
            1       SIMPLE  t1      index|filter    a,b     PRIMARY|a       4|5     NULL    48 (33%)        2.78    Using where; Using rowid filter
            Warnings:
            Note    1003    select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a` between 9 and 10 or `test`.`t1`.`a` is null) and (`test`.`t1`.`b` between 9 and 10 or `test`.`t1`.`b` = 155) order by `test`.`t1`.`pk`
            

            We see that a rowid filter is used with the primary key. Currently such combination is not supported for InnoDB.
            Such combination appeared when a call of test_if_skip_sort_order() changed the originally chosen access by index b for the access by index pk. If this happens we have to make sure that no rowid filter is employed when accessing the table.

            igor Igor Babaev (Inactive) added a comment - 1. The failure is easily reproducible with one run of the test case. 2. If I execute ANALYZE TABLE t1 after the INSERT command the failure cannot be reproduced. 3. Alternatively if I do not use the setting SET global innodb_stats_persistent=on; the failure cannot be reproduced. 4. The cause of the problem can be easily seen if to execute EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a BETWEEN 9 AND 10 OR a IS NULL ) AND (b BETWEEN 9 AND 10 OR b = 155) ORDER BY pk; instead of the corresponding SELECT query: EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a BETWEEN 9 AND 10 OR a IS NULL) AND (b BETWEEN 9 AND 10 OR b = 155) ORDER BY pk; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 index|filter a,b PRIMARY|a 4|5 NULL 48 (33%) 2.78 Using where; Using rowid filter Warnings: Note 1003 select `test`.`t1`.`pk` AS `pk`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a` between 9 and 10 or `test`.`t1`.`a` is null) and (`test`.`t1`.`b` between 9 and 10 or `test`.`t1`.`b` = 155) order by `test`.`t1`.`pk` We see that a rowid filter is used with the primary key. Currently such combination is not supported for InnoDB. Such combination appeared when a call of test_if_skip_sort_order() changed the originally chosen access by index b for the access by index pk. If this happens we have to make sure that no rowid filter is employed when accessing the table.

            The reported test case was not deterministic.
            Here's a deterministic test case for the same bug:

             
            SET @stats.save= @@innodb_stats_persistent;
            SET global innodb_stats_persistent=on;
             
            CREATE TABLE t1 (
                pk int auto_increment,
                a int,
                b int,
                primary key (pk),
                key (a),
                key (b)
            ) ENGINE=InnoDB;
             
            INSERT INTO t1 (a,b) VALUES
            (0,0), (0,9), (0,NULL), (1,2), (4,0), (2,9), (1,0), (NULL,0), (5,NULL), (5,1),
            (0,7), (NULL,5), (NULL,0), (2,1), (2,5), (6,NULL), (0,NULL), (NULL,8), (8,5),
            (2,NULL), (2,3), (NULL,8), (NULL,6), (1,1), (5,1), (NULL,5), (4,4), (2,4),
            (2,5), (1,9), (NULL,0), (3,7), (0,4), (2,8), (1,2), (1,4), (2,1),
            (NULL,7), (6,6), (3,0), (4,5), (5,2), (8,2), (NULL,NULL), (8,NULL),
            (0,1),(0,7);
            INSERT INTO t1(a,b) SELECT a, b FROM t1;
            INSERT INTO t1(a,b) SELECT a, b FROM t1;
            INSERT INTO t1(a,b) SELECT a, b FROM t1;
            INSERT INTO t1(a,b) SELECT a, b FROM t1;
            INSERT INTO t1(a,b) SELECT a, b FROM t1;
            INSERT INTO t1(a,b) SELECT a, b FROM t1;
             
            ANALYZE TABLE t1;
             
            EXPLAIN EXTENDED
            SELECT * FROM t1
              WHERE (a BETWEEN 9 AND 10 OR a IS NULL) AND (b BETWEEN 9 AND 10 OR b = 9);
             
            EXPLAIN EXTENDED
            SELECT * FROM t1
              WHERE (a BETWEEN 9 AND 10 OR a IS NULL) AND (b BETWEEN 9 AND 10 OR b = 9)
            ORDER BY pk LIMIT 1;
             
            ANALYZE
            SELECT * FROM t1
              WHERE (a BETWEEN 9 AND 10 OR a IS NULL) AND (b BETWEEN 9 AND 10 OR b = 9)
            ORDER BY pk LIMIT 1;
             
            DROP TABLE t1;
            SET global innodb_stats_persistent= @stats.save;
            

            igor Igor Babaev (Inactive) added a comment - The reported test case was not deterministic. Here's a deterministic test case for the same bug:   SET @stats.save= @@innodb_stats_persistent; SET global innodb_stats_persistent= on ;   CREATE TABLE t1 ( pk int auto_increment, a int , b int , primary key (pk), key (a), key (b) ) ENGINE=InnoDB;   INSERT INTO t1 (a,b) VALUES (0,0), (0,9), (0, NULL ), (1,2), (4,0), (2,9), (1,0), ( NULL ,0), (5, NULL ), (5,1), (0,7), ( NULL ,5), ( NULL ,0), (2,1), (2,5), (6, NULL ), (0, NULL ), ( NULL ,8), (8,5), (2, NULL ), (2,3), ( NULL ,8), ( NULL ,6), (1,1), (5,1), ( NULL ,5), (4,4), (2,4), (2,5), (1,9), ( NULL ,0), (3,7), (0,4), (2,8), (1,2), (1,4), (2,1), ( NULL ,7), (6,6), (3,0), (4,5), (5,2), (8,2), ( NULL , NULL ), (8, NULL ), (0,1),(0,7); INSERT INTO t1(a,b) SELECT a, b FROM t1; INSERT INTO t1(a,b) SELECT a, b FROM t1; INSERT INTO t1(a,b) SELECT a, b FROM t1; INSERT INTO t1(a,b) SELECT a, b FROM t1; INSERT INTO t1(a,b) SELECT a, b FROM t1; INSERT INTO t1(a,b) SELECT a, b FROM t1;   ANALYZE TABLE t1;   EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a BETWEEN 9 AND 10 OR a IS NULL ) AND (b BETWEEN 9 AND 10 OR b = 9);   EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a BETWEEN 9 AND 10 OR a IS NULL ) AND (b BETWEEN 9 AND 10 OR b = 9) ORDER BY pk LIMIT 1;   ANALYZE SELECT * FROM t1 WHERE (a BETWEEN 9 AND 10 OR a IS NULL ) AND (b BETWEEN 9 AND 10 OR b = 9) ORDER BY pk LIMIT 1;   DROP TABLE t1; SET global innodb_stats_persistent= @stats.save;
            alice Alice Sherepa added a comment -

            not reproducible on the current 10.4 d352bc5b6772f735a7e4b

            alice Alice Sherepa added a comment - not reproducible on the current 10.4 d352bc5b6772f735a7e4b

            Confirmed not reproducible on 10.4 debug a75813d46739f1e3aea9821b163c0ff1332a017e

            Roel Roel Van de Paar added a comment - Confirmed not reproducible on 10.4 debug a75813d46739f1e3aea9821b163c0ff1332a017e

            igor Thoughts?

            Roel Roel Van de Paar added a comment - igor Thoughts?

            It was fixed. Literally, not implicitly:

            commit 7ea413ac2d80c7f03d1dbad90ac30ecddd8b2835
            Author: Igor Babaev
            Date:   Sun Jan 19 20:03:25 2020 -0800
             
                MDEV-21446 Assertion `!prebuilt->index->is_primary()' failed in
                row_search_idx_cond_check with rowid_filter upon concurrent access to table
            

            elenst Elena Stepanova added a comment - It was fixed. Literally, not implicitly: commit 7ea413ac2d80c7f03d1dbad90ac30ecddd8b2835 Author: Igor Babaev Date: Sun Jan 19 20:03:25 2020 -0800   MDEV-21446 Assertion `!prebuilt->index->is_primary()' failed in row_search_idx_cond_check with rowid_filter upon concurrent access to table

            Thank you for fixing bug status

            Roel Roel Van de Paar added a comment - Thank you for fixing bug status

            People

              igor Igor Babaev (Inactive)
              elenst Elena Stepanova
              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.