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

btr_cur_open_at_index_side() is missing some consistency checks

Details

    Description

      In MDEV-13542, many sources of crash on a corrupted page were fixed, but something in the function btr_cur_open_at_index_side() was missed.

      		if (height == ULINT_UNDEFINED) {
      			/* We are in the root node */
       
      			height = btr_page_get_level(page);
      			ut_a(height >= level);
      

      This assertion could fail if a nonzero parameter level was supplied to the function. That is only the case when the inline wrapper function btr_pcur_open_at_index_side() is invoked with level>0, which in turn is only possible in the following functions, related to InnoDB persistent statistics:

      • dict_stats_analyze_index_level()
      • dict_stats_analyze_index_for_n_prefix()

      It would seem to make sense to remove the parameter level from the normal functions, and to write a special function that would be used when computing persistent statistics.

      Furthermore, btr_cur_open_at_index_side() currently fails to return DB_CORRUPTION on PAGE_LEVEL mismatch or when from_left ? !page_has_prev(page) : !page_has_next(page) does not hold.

      Attachments

        Issue Links

          Activity

            Dominant bad effect
            mysqld: /data/Server/bb-10.6-MDEV-29603/storage/innobase/dict/dict0dict.cc:3739: ulint dict_index_check_search_tuple(const dict_index_t*, const dtuple_t*): Assertion `dtuple_get_n_fields_cmp(tuple) <= dict_index_get_n_unique_in_tree(index)' failed.
            (rr) bt
            #0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
            #1  0x00007faaee4ea859 in __GI_abort () at abort.c:79
            #2  0x00007faaee4ea729 in __assert_fail_base (fmt=0x7faaee680588 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x556529ac46c0 "dtuple_get_n_fields_cmp(tuple) <= dict_index_get_n_unique_in_tree(index)", 
                file=0x556529ac0320 "/data/Server/bb-10.6-MDEV-29603/storage/innobase/dict/dict0dict.cc", line=3739, function=<optimized out>) at assert.c:92
            #3  0x00007faaee4fbf36 in __GI___assert_fail (assertion=assertion@entry=0x556529ac46c0 "dtuple_get_n_fields_cmp(tuple) <= dict_index_get_n_unique_in_tree(index)", 
                file=file@entry=0x556529ac0320 "/data/Server/bb-10.6-MDEV-29603/storage/innobase/dict/dict0dict.cc", line=line@entry=3739, 
                function=function@entry=0x556529ac4740 "ulint dict_index_check_search_tuple(const dict_index_t*, const dtuple_t*)") at assert.c:101
            #4  0x0000556528d67266 in dict_index_check_search_tuple (index=index@entry=0x616002586a08, tuple=tuple@entry=0x62d0012fc9b0) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/include/data0data.inl:253
            #5  0x0000556528c473f9 in btr_cur_search_to_nth_level (level=level@entry=0, tuple=tuple@entry=0x62d0012fc9b0, mode=mode@entry=PAGE_CUR_LE, latch_mode=latch_mode@entry=BTR_MODIFY_TREE, cursor=cursor@entry=0x7faacb5a0630, 
                mtr=mtr@entry=0x7faacb5a0d50, autoinc=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/btr/btr0cur.cc:1293
            #6  0x0000556528a29bad in btr_pcur_open (mtr=0x7faacb5a0d50, autoinc=0, cursor=0x7faacb5a0630, latch_mode=BTR_MODIFY_TREE, mode=PAGE_CUR_LE, tuple=0x62d0012fc9b0)
                at /data/Server/bb-10.6-MDEV-29603/storage/innobase/include/btr0pcur.inl:325
            #7  row_search_index_entry (entry=entry@entry=0x62d0012fc9b0, mode=mode@entry=BTR_MODIFY_TREE, pcur=pcur@entry=0x7faacb5a0630, mtr=mtr@entry=0x7faacb5a0d50) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/row/row0row.cc:1286
            #8  0x00005565289dce57 in row_log_table_apply_update (thr=thr@entry=0x619002a3b0c0, new_trx_id_col=new_trx_id_col@entry=1, mrec=mrec@entry=0x7faac6995198 "", offsets=offsets@entry=0x60400007e690, 
                offsets_heap=offsets_heap@entry=0x62d0013ce400, heap=heap@entry=0x62d0012fc400, dup=<optimized out>, old_pk=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/row/row0log.cc:2095
            #9  0x00005565289def22 in row_log_table_apply_op (thr=thr@entry=0x619002a3b0c0, new_trx_id_col=new_trx_id_col@entry=1, dup=dup@entry=0x7faacb5a1c20, error=error@entry=0x7faacb5a1510, 
                offsets_heap=offsets_heap@entry=0x62d0013ce400, heap=heap@entry=0x62d0012fc400, mrec=0x7faac6995198 "", mrec_end=<optimized out>, offsets=<optimized out>)
                at /data/Server/bb-10.6-MDEV-29603/storage/innobase/row/row0log.cc:2392
            #10 0x00005565289e3c4b in row_log_table_apply_ops (thr=thr@entry=0x619002a3b0c0, dup=dup@entry=0x7faacb5a1c20, stage=stage@entry=0x6020004f14f0) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/row/row0log.cc:2762
            #11 0x00005565289e49ff in row_log_table_apply (thr=0x619002a3b0c0, old_table=<optimized out>, table=table@entry=0x7faacb5a34a0, stage=<optimized out>, new_table=<optimized out>)
                at /data/Server/bb-10.6-MDEV-29603/storage/innobase/row/row0log.cc:2870
            #12 0x000055652865fa9b in ha_innobase::inplace_alter_table (this=0x61d000461eb8, altered_table=<optimized out>, ha_alter_info=0x7faacb5a2da0) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/handler/handler0alter.cc:8666
            #13 0x00005565275fa1a6 in handler::ha_inplace_alter_table (ha_alter_info=0x7faacb5a2da0, altered_table=0x7faacb5a34a0, this=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/sql/handler.h:4676
            #14 mysql_inplace_alter_table (thd=thd@entry=0x62b0001ff218, table_list=<optimized out>, table=table@entry=0x619002b03998, altered_table=<optimized out>, ha_alter_info=0x7faacb5a2da0, target_mdl_request=<optimized out>, 
                ddl_log_state=<optimized out>, trigger_param=<optimized out>, alter_ctx=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/sql/sql_table.cc:7420
            #15 0x00005565276311e4 in mysql_alter_table (thd=thd@entry=0x62b0001ff218, new_db=new_db@entry=0x62b000203c48, new_name=new_name@entry=0x62b000204060, create_info=0x7faacb5a5820, table_list=<optimized out>, 
                table_list@entry=0x62b0002063d0, alter_info=<optimized out>, order_num=<optimized out>, order=<optimized out>, ignore=<optimized out>, if_exists=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/sql/sql_table.cc:10335
            #16 0x00005565277b9c7b in Sql_cmd_alter_table::execute (this=<optimized out>, thd=0x62b0001ff218) at /data/Server/bb-10.6-MDEV-29603/sql/structs.h:568
            #17 0x0000556527382bc1 in mysql_execute_command (thd=thd@entry=0x62b0001ff218, is_called_from_prepared_stmt=is_called_from_prepared_stmt@entry=false) at /data/Server/bb-10.6-MDEV-29603/sql/sql_parse.cc:5997
            #18 0x0000556527339d24 in mysql_parse (thd=thd@entry=0x62b0001ff218, rawbuf=<optimized out>, length=<optimized out>, parser_state=parser_state@entry=0x7faacb5a7130) at /data/Server/bb-10.6-MDEV-29603/sql/sql_parse.cc:8016
            #19 0x00005565273682d1 in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x62b0001ff218, 
                packet=packet@entry=0x62900185b219 "ALTER TABLE `t6` PAGE_COMPRESSED=0 ENCRYPTION_KEY_ID=2 /* E_R Thread20 QNO 8 CON_ID 35 */ ", packet_length=packet_length@entry=90, blocking=blocking@entry=true)
                at /data/Server/bb-10.6-MDEV-29603/sql/sql_class.h:1362
            #20 0x000055652736efb8 in do_command (thd=0x62b0001ff218, blocking=blocking@entry=true) at /data/Server/bb-10.6-MDEV-29603/sql/sql_parse.cc:1409
            #21 0x00005565277a2fdd in do_handle_one_connection (connect=<optimized out>, connect@entry=0x608000003838, put_in_cache=put_in_cache@entry=true) at /data/Server/bb-10.6-MDEV-29603/sql/sql_connect.cc:1416
            #22 0x00005565277a3b26 in handle_one_connection (arg=0x608000003838) at /data/Server/bb-10.6-MDEV-29603/sql/sql_connect.cc:1318
            #23 0x00007faaeea12609 in start_thread (arg=<optimized out>) at pthread_create.c:477
            #24 0x00007faaee5e7293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
            (rr)
            pluto:/data/results/1667480093/TBR-562$ _RR_TRACE_DIR=./1/rr/ rr replay --mark-stdio
             
            The bad effect TBR-562 was observed first time April 2020 and last time before December 2020.
             
            
            

            mleich Matthias Leich added a comment - Dominant bad effect mysqld: /data/Server/bb-10.6-MDEV-29603/storage/innobase/dict/dict0dict.cc:3739: ulint dict_index_check_search_tuple(const dict_index_t*, const dtuple_t*): Assertion `dtuple_get_n_fields_cmp(tuple) <= dict_index_get_n_unique_in_tree(index)' failed. (rr) bt #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50 #1 0x00007faaee4ea859 in __GI_abort () at abort.c:79 #2 0x00007faaee4ea729 in __assert_fail_base (fmt=0x7faaee680588 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x556529ac46c0 "dtuple_get_n_fields_cmp(tuple) <= dict_index_get_n_unique_in_tree(index)", file=0x556529ac0320 "/data/Server/bb-10.6-MDEV-29603/storage/innobase/dict/dict0dict.cc", line=3739, function=<optimized out>) at assert.c:92 #3 0x00007faaee4fbf36 in __GI___assert_fail (assertion=assertion@entry=0x556529ac46c0 "dtuple_get_n_fields_cmp(tuple) <= dict_index_get_n_unique_in_tree(index)", file=file@entry=0x556529ac0320 "/data/Server/bb-10.6-MDEV-29603/storage/innobase/dict/dict0dict.cc", line=line@entry=3739, function=function@entry=0x556529ac4740 "ulint dict_index_check_search_tuple(const dict_index_t*, const dtuple_t*)") at assert.c:101 #4 0x0000556528d67266 in dict_index_check_search_tuple (index=index@entry=0x616002586a08, tuple=tuple@entry=0x62d0012fc9b0) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/include/data0data.inl:253 #5 0x0000556528c473f9 in btr_cur_search_to_nth_level (level=level@entry=0, tuple=tuple@entry=0x62d0012fc9b0, mode=mode@entry=PAGE_CUR_LE, latch_mode=latch_mode@entry=BTR_MODIFY_TREE, cursor=cursor@entry=0x7faacb5a0630, mtr=mtr@entry=0x7faacb5a0d50, autoinc=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/btr/btr0cur.cc:1293 #6 0x0000556528a29bad in btr_pcur_open (mtr=0x7faacb5a0d50, autoinc=0, cursor=0x7faacb5a0630, latch_mode=BTR_MODIFY_TREE, mode=PAGE_CUR_LE, tuple=0x62d0012fc9b0) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/include/btr0pcur.inl:325 #7 row_search_index_entry (entry=entry@entry=0x62d0012fc9b0, mode=mode@entry=BTR_MODIFY_TREE, pcur=pcur@entry=0x7faacb5a0630, mtr=mtr@entry=0x7faacb5a0d50) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/row/row0row.cc:1286 #8 0x00005565289dce57 in row_log_table_apply_update (thr=thr@entry=0x619002a3b0c0, new_trx_id_col=new_trx_id_col@entry=1, mrec=mrec@entry=0x7faac6995198 "", offsets=offsets@entry=0x60400007e690, offsets_heap=offsets_heap@entry=0x62d0013ce400, heap=heap@entry=0x62d0012fc400, dup=<optimized out>, old_pk=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/row/row0log.cc:2095 #9 0x00005565289def22 in row_log_table_apply_op (thr=thr@entry=0x619002a3b0c0, new_trx_id_col=new_trx_id_col@entry=1, dup=dup@entry=0x7faacb5a1c20, error=error@entry=0x7faacb5a1510, offsets_heap=offsets_heap@entry=0x62d0013ce400, heap=heap@entry=0x62d0012fc400, mrec=0x7faac6995198 "", mrec_end=<optimized out>, offsets=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/row/row0log.cc:2392 #10 0x00005565289e3c4b in row_log_table_apply_ops (thr=thr@entry=0x619002a3b0c0, dup=dup@entry=0x7faacb5a1c20, stage=stage@entry=0x6020004f14f0) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/row/row0log.cc:2762 #11 0x00005565289e49ff in row_log_table_apply (thr=0x619002a3b0c0, old_table=<optimized out>, table=table@entry=0x7faacb5a34a0, stage=<optimized out>, new_table=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/row/row0log.cc:2870 #12 0x000055652865fa9b in ha_innobase::inplace_alter_table (this=0x61d000461eb8, altered_table=<optimized out>, ha_alter_info=0x7faacb5a2da0) at /data/Server/bb-10.6-MDEV-29603/storage/innobase/handler/handler0alter.cc:8666 #13 0x00005565275fa1a6 in handler::ha_inplace_alter_table (ha_alter_info=0x7faacb5a2da0, altered_table=0x7faacb5a34a0, this=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/sql/handler.h:4676 #14 mysql_inplace_alter_table (thd=thd@entry=0x62b0001ff218, table_list=<optimized out>, table=table@entry=0x619002b03998, altered_table=<optimized out>, ha_alter_info=0x7faacb5a2da0, target_mdl_request=<optimized out>, ddl_log_state=<optimized out>, trigger_param=<optimized out>, alter_ctx=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/sql/sql_table.cc:7420 #15 0x00005565276311e4 in mysql_alter_table (thd=thd@entry=0x62b0001ff218, new_db=new_db@entry=0x62b000203c48, new_name=new_name@entry=0x62b000204060, create_info=0x7faacb5a5820, table_list=<optimized out>, table_list@entry=0x62b0002063d0, alter_info=<optimized out>, order_num=<optimized out>, order=<optimized out>, ignore=<optimized out>, if_exists=<optimized out>) at /data/Server/bb-10.6-MDEV-29603/sql/sql_table.cc:10335 #16 0x00005565277b9c7b in Sql_cmd_alter_table::execute (this=<optimized out>, thd=0x62b0001ff218) at /data/Server/bb-10.6-MDEV-29603/sql/structs.h:568 #17 0x0000556527382bc1 in mysql_execute_command (thd=thd@entry=0x62b0001ff218, is_called_from_prepared_stmt=is_called_from_prepared_stmt@entry=false) at /data/Server/bb-10.6-MDEV-29603/sql/sql_parse.cc:5997 #18 0x0000556527339d24 in mysql_parse (thd=thd@entry=0x62b0001ff218, rawbuf=<optimized out>, length=<optimized out>, parser_state=parser_state@entry=0x7faacb5a7130) at /data/Server/bb-10.6-MDEV-29603/sql/sql_parse.cc:8016 #19 0x00005565273682d1 in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x62b0001ff218, packet=packet@entry=0x62900185b219 "ALTER TABLE `t6` PAGE_COMPRESSED=0 ENCRYPTION_KEY_ID=2 /* E_R Thread20 QNO 8 CON_ID 35 */ ", packet_length=packet_length@entry=90, blocking=blocking@entry=true) at /data/Server/bb-10.6-MDEV-29603/sql/sql_class.h:1362 #20 0x000055652736efb8 in do_command (thd=0x62b0001ff218, blocking=blocking@entry=true) at /data/Server/bb-10.6-MDEV-29603/sql/sql_parse.cc:1409 #21 0x00005565277a2fdd in do_handle_one_connection (connect=<optimized out>, connect@entry=0x608000003838, put_in_cache=put_in_cache@entry=true) at /data/Server/bb-10.6-MDEV-29603/sql/sql_connect.cc:1416 #22 0x00005565277a3b26 in handle_one_connection (arg=0x608000003838) at /data/Server/bb-10.6-MDEV-29603/sql/sql_connect.cc:1318 #23 0x00007faaeea12609 in start_thread (arg=<optimized out>) at pthread_create.c:477 #24 0x00007faaee5e7293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 (rr) pluto:/data/results/1667480093/TBR-562$ _RR_TRACE_DIR=./1/rr/ rr replay --mark-stdio   The bad effect TBR-562 was observed first time April 2020 and last time before December 2020.  

            In row_log_table_update(), we are creating a search tuple for a secondary index, but the cursor that is passed to btr_pcur_open() points to the clustered index of the table. The branch contains many changes related to iterating B-trees, including some that may ultimately be part of MDEV-29835 rather than this ticket. Previously, several pointers to an index were being passed to btr_pcur_open(). When I removed the redundant function parameter and the redundant data member btr_cur_t::index, I forgot to assign page_cur_t::index in this code path.

            marko Marko Mäkelä added a comment - In row_log_table_update() , we are creating a search tuple for a secondary index, but the cursor that is passed to btr_pcur_open() points to the clustered index of the table. The branch contains many changes related to iterating B-trees, including some that may ultimately be part of MDEV-29835 rather than this ticket. Previously, several pointers to an index were being passed to btr_pcur_open() . When I removed the redundant function parameter and the redundant data member btr_cur_t::index , I forgot to assign page_cur_t::index in this code path.

            I am working on a change that simplifies the way how dict_stats_analyze_index() works. That is the only user of code that needs to open the first or last page at a specific tree level, actually always the first page, and always S-latched. This will depend on the ability of mtr_t::rollback_to_savepoint() to shrink the mtr_t::m_memo, or on a new operation that will rollback to savepoint everything but the last object (that is, release all upper page latches, but retain the index latch and one page latch).

            I already refactored mtr_t::m_memo to use std::vector instead of the homebrew mtr_buf_t. That change should also be helpful in a reimplementation of the B-tree cursor operations in MDEV-29835.

            marko Marko Mäkelä added a comment - I am working on a change that simplifies the way how dict_stats_analyze_index() works. That is the only user of code that needs to open the first or last page at a specific tree level, actually always the first page, and always S-latched. This will depend on the ability of mtr_t::rollback_to_savepoint() to shrink the mtr_t::m_memo , or on a new operation that will rollback to savepoint everything but the last object (that is, release all upper page latches, but retain the index latch and one page latch). I already refactored mtr_t::m_memo to use std::vector instead of the homebrew mtr_buf_t . That change should also be helpful in a reimplementation of the B-tree cursor operations in MDEV-29835 .

            The function btr_cur_open_at_index_side() was replaced with btr_cur_t::open_leaf() and a statistics-specific function page_cur_open_level(). Some redundant parameters around InnoDB cursor opeartions and the redundant data member btr_cur_t::index were removed, mtr_t::m_memo was replaced with std::vector and many operations related to mtr_t::m_memo were simplified.

            Thanks to mleich for testing and vlad.lesin for reviewing the changes. This paves the way to fix MDEV-29835.

            marko Marko Mäkelä added a comment - The function btr_cur_open_at_index_side() was replaced with btr_cur_t::open_leaf() and a statistics-specific function page_cur_open_level() . Some redundant parameters around InnoDB cursor opeartions and the redundant data member btr_cur_t::index were removed, mtr_t::m_memo was replaced with std::vector and many operations related to mtr_t::m_memo were simplified. Thanks to mleich for testing and vlad.lesin for reviewing the changes. This paves the way to fix MDEV-29835 .

            People

              marko Marko Mäkelä
              marko Marko Mäkelä
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

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