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

Assertion `0' failed in Protocol::end_statement on query from I_S and mysql.user, join_cache_level > 2

Details

    Description

      SET join_cache_level = 3;
      SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user WHERE password_expired = PAGE_FAULTS_MINOR;

      #6  0x00007f61677866f1 in *__GI___assert_fail (assertion=0xf0eab0 "0", file=<optimized out>, line=521, function=0xf0ffc0 "void Protocol::end_statement()") at assert.c:81
      #7  0x00000000005d1b83 in Protocol::end_statement (this=0x7f616232f5f8) at 10.0/sql/protocol.cc:521
      #8  0x000000000067881e in dispatch_command (command=COM_QUERY, thd=0x7f616232f070, packet=0x7f61633f6071 "SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user WHERE password_expired = PAGE_FAULTS_MINOR", packet_length=97) at 10.0/sql/sql_parse.cc:1728
      #9  0x0000000000676795 in do_command (thd=0x7f616232f070) at 10.0/sql/sql_parse.cc:1004
      #10 0x0000000000792a96 in do_handle_one_connection (thd_arg=0x7f616232f070) at 10.0/sql/sql_connect.cc:1379
      #11 0x00000000007927e9 in handle_one_connection (arg=0x7f616232f070) at 10.0/sql/sql_connect.cc:1293
      #12 0x0000000000cc5296 in pfs_spawn_thread (arg=0x7f616171fbf0) at 10.0/storage/perfschema/pfs.cc:1860
      #13 0x00007f616933fb50 in start_thread (arg=<optimized out>) at pthread_create.c:304
      #14 0x00007f616783720d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112

      Stack trace from:

      revision-id: knielsen@knielsen-hq.org-20140902120701-txesdmkczel84qgf
      revno: 4369
      branch-nick: 10.0

      EXPLAIN also crashes.

      Attachments

        Activity

          cvicentiu, please investigate.

          Initial ideas (I might be wrong): something failed with an error but failed to print the error to network. We fail assert at the end of the statement, where we attempt to make an impossible state transition in the client-server protocol.
          Is it possible to produce an EXPLAIN for this query with a lower @@join_cache_level ?
          AFAIU, INFORMATION_SCHEMA.PROFILING is a special kind of table, its handler may cause bugs when one is trying to do joins with it.

          psergei Sergei Petrunia added a comment - cvicentiu , please investigate. Initial ideas (I might be wrong): something failed with an error but failed to print the error to network. We fail assert at the end of the statement, where we attempt to make an impossible state transition in the client-server protocol. Is it possible to produce an EXPLAIN for this query with a lower @@join_cache_level ? AFAIU, INFORMATION_SCHEMA.PROFILING is a special kind of table, its handler may cause bugs when one is trying to do joins with it.

          Running this from commit version f37bdd9c1a29865 from 10.0 branch, causes a segfault instead.

          The problem is apparently in sql/sql_select.cc:8809

          j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();

          keyuse->val is an Item_field, pointing to PAGE_FAULTS_MINOR. It is however called as an Item_func and this leads to a subsequent crash.

          cvicentiu Vicențiu Ciorbaru added a comment - Running this from commit version f37bdd9c1a29865 from 10.0 branch, causes a segfault instead. The problem is apparently in sql/sql_select.cc:8809 j->ref.items[0]=((Item_func*)(keyuse->val))->key_item(); keyuse->val is an Item_field, pointing to PAGE_FAULTS_MINOR. It is however called as an Item_func and this leads to a subsequent crash.

          cvicentiu, thanks for the info. Next time please provide a stack trace, too.

          For me, debug build of current 10.0 crashes here:

            0x000000000087dd2f in Item::init_make_field (this=0x7ffe98007600, tmp_field=0x0, field_type_arg=MYSQL_TYPE_LONG) at /home/psergey/dev-git/10.0/sql/item.cc:5526
          (gdb) p tmp_field
            $82 = (Send_field *) 0x0
          (gdb) wher
            #0  0x000000000087dd2f in Item::init_make_field (this=0x7ffe98007600, tmp_field=0x0, field_type_arg=MYSQL_TYPE_LONG) at /home/psergey/dev-git/10.0/sql/item.cc:5526
            #1  0x000000000087de56 in Item::make_field (this=0x7ffe98007600, tmp_field=0x0) at /home/psergey/dev-git/10.0/sql/item.cc:5544
            #2  0x00000000006aff74 in create_ref_for_key (join=0x7ffe9800a228, j=0x7ffe98016c38, org_keyuse=0x7ffe980172d0, allow_full_scan=true, used_tables=4611686018427387907) at /home/psergey/dev-git/10.0/sql/sql_select.cc:8809
            #3  0x00000000006af260 in get_best_combination (join=0x7ffe9800a228) at /home/psergey/dev-git/10.0/sql/sql_select.cc:8518
            #4  0x00000000006a4f32 in make_join_statistics (join=0x7ffe9800a228, tables_list=..., conds=0x7ffe98007700, keyuse_array=0x7ffe9800a530) at /home/psergey/dev-git/10.0/sql/sql_select.cc:4072
            #5  0x000000000069b39f in JOIN::optimize_inner (this=0x7ffe9800a228) at /home/psergey/dev-git/10.0/sql/sql_select.cc:1339
            #6  0x000000000069a2e0 in JOIN::optimize (this=0x7ffe9800a228) at /home/psergey/dev-git/10.0/sql/sql_select.cc:1024
            #7  0x00000000006a2175 in mysql_select (thd=0xe6ac360, rref_pointer_array=0xe6b09d8, tables=0x7ffe980068b0, wild_num=1, fields=..., conds=0x7ffe98007700, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2684619520, result=0x7ffe9800a208, unit=0xe6b0070, select_lex=0xe6b0760) at /home/psergey/dev-git/10.0/sql/sql_select.cc:3296
            #8  0x00000000006984eb in handle_select (thd=0xe6ac360, lex=0xe6affa8, result=0x7ffe9800a208, setup_tables_done_option=0) at /home/psergey/dev-git/10.0/sql/sql_select.cc:373
            #9  0x000000000066b916 in execute_sqlcom_select (thd=0xe6ac360, all_tables=0x7ffe980068b0) at /home/psergey/dev-git/10.0/sql/sql_parse.cc:5258
            #10 0x00000000006638d6 in mysql_execute_command (thd=0xe6ac360) at /home/psergey/dev-git/10.0/sql/sql_parse.cc:2546
            #11 0x000000000066e601 in mysql_parse (thd=0xe6ac360, rawbuf=0x7ffe98006608 "SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user WHERE password_expired = PAGE_FAULTS_MINOR", length=97, parser_state=0x7ffff7f82530) at /home/psergey/dev-git/10.0/sql/sql_parse.cc:6513

          psergei Sergei Petrunia added a comment - cvicentiu , thanks for the info. Next time please provide a stack trace, too. For me, debug build of current 10.0 crashes here: 0x000000000087dd2f in Item::init_make_field (this=0x7ffe98007600, tmp_field=0x0, field_type_arg=MYSQL_TYPE_LONG) at /home/psergey/dev-git/10.0/sql/item.cc:5526 (gdb) p tmp_field $82 = (Send_field *) 0x0 (gdb) wher #0 0x000000000087dd2f in Item::init_make_field (this=0x7ffe98007600, tmp_field=0x0, field_type_arg=MYSQL_TYPE_LONG) at /home/psergey/dev-git/10.0/sql/item.cc:5526 #1 0x000000000087de56 in Item::make_field (this=0x7ffe98007600, tmp_field=0x0) at /home/psergey/dev-git/10.0/sql/item.cc:5544 #2 0x00000000006aff74 in create_ref_for_key (join=0x7ffe9800a228, j=0x7ffe98016c38, org_keyuse=0x7ffe980172d0, allow_full_scan=true, used_tables=4611686018427387907) at /home/psergey/dev-git/10.0/sql/sql_select.cc:8809 #3 0x00000000006af260 in get_best_combination (join=0x7ffe9800a228) at /home/psergey/dev-git/10.0/sql/sql_select.cc:8518 #4 0x00000000006a4f32 in make_join_statistics (join=0x7ffe9800a228, tables_list=..., conds=0x7ffe98007700, keyuse_array=0x7ffe9800a530) at /home/psergey/dev-git/10.0/sql/sql_select.cc:4072 #5 0x000000000069b39f in JOIN::optimize_inner (this=0x7ffe9800a228) at /home/psergey/dev-git/10.0/sql/sql_select.cc:1339 #6 0x000000000069a2e0 in JOIN::optimize (this=0x7ffe9800a228) at /home/psergey/dev-git/10.0/sql/sql_select.cc:1024 #7 0x00000000006a2175 in mysql_select (thd=0xe6ac360, rref_pointer_array=0xe6b09d8, tables=0x7ffe980068b0, wild_num=1, fields=..., conds=0x7ffe98007700, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2684619520, result=0x7ffe9800a208, unit=0xe6b0070, select_lex=0xe6b0760) at /home/psergey/dev-git/10.0/sql/sql_select.cc:3296 #8 0x00000000006984eb in handle_select (thd=0xe6ac360, lex=0xe6affa8, result=0x7ffe9800a208, setup_tables_done_option=0) at /home/psergey/dev-git/10.0/sql/sql_select.cc:373 #9 0x000000000066b916 in execute_sqlcom_select (thd=0xe6ac360, all_tables=0x7ffe980068b0) at /home/psergey/dev-git/10.0/sql/sql_parse.cc:5258 #10 0x00000000006638d6 in mysql_execute_command (thd=0xe6ac360) at /home/psergey/dev-git/10.0/sql/sql_parse.cc:2546 #11 0x000000000066e601 in mysql_parse (thd=0xe6ac360, rawbuf=0x7ffe98006608 "SELECT * FROM INFORMATION_SCHEMA.PROFILING, mysql.user WHERE password_expired = PAGE_FAULTS_MINOR", length=97, parser_state=0x7ffff7f82530) at /home/psergey/dev-git/10.0/sql/sql_parse.cc:6513

          It's actually the same place. The last stack frame that makes sense is create_ref_for_key, this line:

              j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();

          where keyuse->val is an Item_field, which is not inherited from Item_func.
          Another odd thing: ftkey==true, although the query is not using fulltext indexes in any way.

          psergei Sergei Petrunia added a comment - It's actually the same place. The last stack frame that makes sense is create_ref_for_key, this line: j->ref.items[0]=((Item_func*)(keyuse->val))->key_item(); where keyuse->val is an Item_field, which is not inherited from Item_func. Another odd thing: ftkey==true, although the query is not using fulltext indexes in any way.

          Query plan with default join_cache_level:

          +------+-------------+-----------+------+---------------+------+---------+------+------+-------------------------------------------------+
          | id   | select_type | table     | type | possible_keys | key  | key_len | ref  | rows | Extra                                           |
          +------+-------------+-----------+------+---------------+------+---------+------+------+-------------------------------------------------+
          |    1 | SIMPLE      | PROFILING | ALL  | NULL          | NULL | NULL    | NULL | NULL |                                                 |
          |    1 | SIMPLE      | user      | ALL  | NULL          | NULL | NULL    | NULL |    4 | Using where; Using join buffer (flat, BNL join) |
          +------+-------------+-----------+------+---------------+------+---------+------+------+-------------------------------------------------+

          The order of JOIN_TABs for the crashing scenario is the same.
          We crash when get_best_combination() processes the second JOIN_TAB.

          It seems like table 'user' is accessed through hash join:

          • tab->type=JT_REF, even if the table has no usable indexes
          • create_ref_for_key() calls create_hj_key_for_table which seems to do something meaningful.

          At the same time, something weird is going on: ftkey=true.

          psergei Sergei Petrunia added a comment - Query plan with default join_cache_level: +------+-------------+-----------+------+---------------+------+---------+------+------+-------------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+-----------+------+---------------+------+---------+------+------+-------------------------------------------------+ | 1 | SIMPLE | PROFILING | ALL | NULL | NULL | NULL | NULL | NULL | | | 1 | SIMPLE | user | ALL | NULL | NULL | NULL | NULL | 4 | Using where; Using join buffer (flat, BNL join) | +------+-------------+-----------+------+---------------+------+---------+------+------+-------------------------------------------------+ The order of JOIN_TABs for the crashing scenario is the same. We crash when get_best_combination() processes the second JOIN_TAB. It seems like table 'user' is accessed through hash join: tab->type=JT_REF, even if the table has no usable indexes create_ref_for_key() calls create_hj_key_for_table which seems to do something meaningful. At the same time, something weird is going on: ftkey=true.
          psergei Sergei Petrunia added a comment - - edited

          #define FT_KEYPART   (MAX_REF_PARTS+10)
          ...
          #define MAX_REF_PARTS 32			/* Max parts used as ref */

          (gdb) p keyuse->keypart
            $131 = 42
          (gdb)  
          (gdb) p keyuse->key
            $132 = 64

          So, key=MAX_KEY, which says this is hash join. But then, keypart=MAX_REF_PARTS + 10, which makes the code think it's a fulltex scan.

          psergei Sergei Petrunia added a comment - - edited #define FT_KEYPART (MAX_REF_PARTS+10) ... #define MAX_REF_PARTS 32 /* Max parts used as ref */ (gdb) p keyuse->keypart $131 = 42 (gdb) (gdb) p keyuse->key $132 = 64 So, key=MAX_KEY, which says this is hash join. But then, keypart=MAX_REF_PARTS + 10, which makes the code think it's a fulltex scan.

          Tracking where keypart=42 value came from. It's from add_keyuse(), from here:

            if (!is_hash_join_key_no(key))
            {
              keyuse.keypart=part;
              keyuse.keypart_map= (key_part_map) 1 << part;
            }
            else
            {
              keyuse.keypart= field->field_index;
              keyuse.keypart_map= (key_part_map) 0;
            }

          field->field_index=42.

          psergei Sergei Petrunia added a comment - Tracking where keypart=42 value came from. It's from add_keyuse(), from here: if (!is_hash_join_key_no(key)) { keyuse.keypart=part; keyuse.keypart_map= (key_part_map) 1 << part; } else { keyuse.keypart= field->field_index; keyuse.keypart_map= (key_part_map) 0; } field->field_index=42.

          That is, before hash join code it was safe to define FT_KEYPART as

          FT_KEYPART   (MAX_REF_PARTS+10)

          but since hash join code stores field numbers (instead of key part numbers) there, there is a possibility for collisions. As for number of fields:

          #define MAX_FIELDS	4096			/* Limit in the .frm file */

          Is it safe to declare FT_KEYPART as MAX_FIELDS + 10 ? (Does anybody use 1-byte storage for storing key_part_number?)

          psergei Sergei Petrunia added a comment - That is, before hash join code it was safe to define FT_KEYPART as FT_KEYPART (MAX_REF_PARTS+10) but since hash join code stores field numbers (instead of key part numbers) there, there is a possibility for collisions. As for number of fields: #define MAX_FIELDS 4096 /* Limit in the .frm file */ Is it safe to declare FT_KEYPART as MAX_FIELDS + 10 ? (Does anybody use 1-byte storage for storing key_part_number?)

          People

            psergei Sergei Petrunia
            elenst Elena Stepanova
            Votes:
            0 Vote for this issue
            Watchers:
            4 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.