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

Server crash on a JOIN on a derived table with join_cache_level > 2

Details

    • Bug
    • Status: Closed (View Workflow)
    • Critical
    • Resolution: Fixed
    • 5.5.32, 5.5.33
    • 5.5.34
    • None
    • Debian Squeeze amd64 5.5.32 & Debian Squeeze amd64 5.5.33
      (packaged versions)

    Description

      While the join_cache_level variable is set to a value > 2, a query with a join on a derived table with a TEXT column in it could result to a server crash when LIMIT x OFFSET x is used on the derived table.

      To reproduce the crash, import the attached SQL then execute the following query :

      EXPLAIN SELECT 1 FROM (SELECT url, id FROM t2 LIMIT 1 OFFSET 20) derived RIGHT JOIN t1 ON t1.id = derived.id;

      Here is the error log output :

      mysqld: 130919 14:11:26 [ERROR] mysqld got signal 11 ;
      mysqld: This could be because you hit a bug. It is also possible that this binary
      mysqld: or one of the libraries it was linked against is corrupt, improperly built,
      mysqld: or misconfigured. This error can also be caused by malfunctioning hardware.
      mysqld: 
      mysqld: To report this bug, see http://kb.askmonty.org/en/reporting-bugs
      mysqld: 
      mysqld: We will try our best to scrape up some info that will hopefully help
      mysqld: diagnose the problem, but since we have already crashed, 
      mysqld: something is definitely wrong and this may fail.
      mysqld: 
      mysqld: Server version: 5.5.33-MariaDB-1~squeeze
      mysqld: key_buffer_size=2147483648
      mysqld: read_buffer_size=2097152
      mysqld: max_used_connections=1
      mysqld: max_threads=252
      mysqld: thread_count=1
      mysqld: It is possible that mysqld could use up to 
      mysqld: key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 3133826 K  bytes of memory
      mysqld: Hope that's ok; if not, decrease some variables in the equation.
      mysqld: 
      mysqld: Thread pointer: 0x0x7fb69bcfb5f0
      mysqld: Attempting backtrace. You can use the following information to find out
      mysqld: where mysqld died. If you see no messages after this, something went
      mysqld: terribly wrong...
      mysqld: stack_bottom = 0x7fb37714ae58 thread_stack 0x48000
      mysqld: /usr/sbin/mysqld(my_print_stacktrace+0x2e)[0x7fb69035d80e]
      mysqld: /usr/sbin/mysqld(handle_fatal_signal+0x4ac)[0x7fb68ff5cd7c]
      mysqld: /lib/libpthread.so.0(+0xeff0)[0x7fb68f659ff0]
      mysqld: /usr/sbin/mysqld(_ZN10DsMrr_impl15choose_mrr_implEjyPjS0_P9COST_VECT+0x54)[0x7fb68feff724]
      mysqld: /usr/sbin/mysqld(_ZN10DsMrr_impl10dsmrr_infoEjjjjPjS0_P9COST_VECT+0xe3)[0x7fb68feffad3]
      mysqld: /usr/sbin/mysqld(_Z33check_join_cache_usage_for_tablesP4JOINyj+0x694)[0x7fb68fe40ed4]
      mysqld: /usr/sbin/mysqld(_ZN4JOIN8optimizeEv+0x16c7)[0x7fb68fe4f477]
      mysqld: /usr/sbin/mysqld(_Z12mysql_selectP3THDPPP4ItemP10TABLE_LISTjR4ListIS1_ES2_jP8st_orderSB_S2_SB_yP13select_resultP18st_select_lex_unitP13st_select_lex+0xd2)[0x7fb68fe568e2]
      mysqld: /usr/sbin/mysqld(_Z19mysql_explain_unionP3THDP18st_select_lex_unitP13select_result+0x10c)[0x7fb68fe5726c]
      mysqld: /usr/sbin/mysqld(+0x37771f)[0x7fb68fdfe71f]
      mysqld: /usr/sbin/mysqld(_Z21mysql_execute_commandP3THD+0x35f9)[0x7fb68fe05539]
      mysqld: /usr/sbin/mysqld(_Z11mysql_parseP3THDPcjP12Parser_state+0x1cc)[0x7fb68fe080ec]
      mysqld: /usr/sbin/mysqld(_Z16dispatch_command19enum_server_commandP3THDPcj+0x1792)[0x7fb68fe09892]
      mysqld: /usr/sbin/mysqld(_Z24do_handle_one_connectionP3THD+0x419)[0x7fb68fece809]
      mysqld: /usr/sbin/mysqld(handle_one_connection+0x51)[0x7fb68fece8c1]
      mysqld: /lib/libpthread.so.0(+0x68ca)[0x7fb68f6518ca]
      mysqld: /lib/libc.so.6(clone+0x6d)[0x7fb68dfd0b6d]
      mysqld: 
      mysqld: Trying to get some variables.
      mysqld: Some pointers may be invalid and cause the dump to abort.
      mysqld: Query (0x7fb69bd467f8): EXPLAIN SELECT 1 FROM (SELECT url, id FROM t2 LIMIT 1 OFFSET 20) derived RIGHT JOIN t1 ON t1.id = derived.id
      mysqld: 
      mysqld: Connection ID (thread ID): 1
      mysqld: Status: NOT_KILLED
      mysqld: 
      mysqld: 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=off
      mysqld: 
      mysqld: The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
      mysqld: information that should help you find out what is causing the crash.
      mysqld_safe: Number of processes running now: 0
      mysqld_safe: mysqld restarted

      Attachments

        Activity

          Program received signal SIGSEGV, Segmentation fault.
          [Switching to Thread 0x7ffff7f8d700 (LWP 8548)]
          0x0000000000742b3c in DsMrr_impl::check_cpk_scan (this=0x7fffb4ced4b8, thd=0x7fffc3fe9060, keyno=0, mrr_flags=129) at /home/psergey/dev2/5.5/sql/multi_range_read.cc:1523
          Missing separate debuginfos, use: debuginfo-install zlib-1.2.5-6.fc16.x86_64
          (gdb) p this
          $2 = (DsMrr_impl * const) 0x7fffb4ced4b8
          (gdb) print table
          $4 = (TABLE *) 0x0

          up
          up
          up

          #4 0x00000000006524fe in check_join_cache_usage (tab=0x7fffb4c62800, options=4, no_jbuf_after=2, table_index=1, prev_tab=0x7fffb4c624e0) at /home/psergey/dev2/5.5/sql/sql_select.cc:9798

          (gdb) list
          9793 flags= HA_MRR_NO_NULL_ENDPOINTS | HA_MRR_SINGLE_POINT;
          9794 if (tab->table->covering_keys.is_set(tab->ref.key))
          9795 flags|= HA_MRR_INDEX_ONLY;
          9796 rows= tab->table->file->multi_range_read_info(tab->ref.key, 10, 20,
          9797 tab->ref.key_parts,
          9798 &bufsz, &flags, &cost);
          9799 }

          (gdb) p tab->table
          $18 = (TABLE *) 0x7fffb4c9d078

          (gdb) p tab->table->alias.Ptr
          $22 = 0x7fffb4c46c78 "derived"

          psergei Sergei Petrunia added a comment - Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x7ffff7f8d700 (LWP 8548)] 0x0000000000742b3c in DsMrr_impl::check_cpk_scan (this=0x7fffb4ced4b8, thd=0x7fffc3fe9060, keyno=0, mrr_flags=129) at /home/psergey/dev2/5.5/sql/multi_range_read.cc:1523 Missing separate debuginfos, use: debuginfo-install zlib-1.2.5-6.fc16.x86_64 (gdb) p this $2 = (DsMrr_impl * const) 0x7fffb4ced4b8 (gdb) print table $4 = (TABLE *) 0x0 up up up #4 0x00000000006524fe in check_join_cache_usage (tab=0x7fffb4c62800, options=4, no_jbuf_after=2, table_index=1, prev_tab=0x7fffb4c624e0) at /home/psergey/dev2/5.5/sql/sql_select.cc:9798 (gdb) list 9793 flags= HA_MRR_NO_NULL_ENDPOINTS | HA_MRR_SINGLE_POINT; 9794 if (tab->table->covering_keys.is_set(tab->ref.key)) 9795 flags|= HA_MRR_INDEX_ONLY; 9796 rows= tab->table->file->multi_range_read_info(tab->ref.key, 10, 20, 9797 tab->ref.key_parts, 9798 &bufsz, &flags, &cost); 9799 } (gdb) p tab->table $18 = (TABLE *) 0x7fffb4c9d078 (gdb) p tab->table->alias.Ptr $22 = 0x7fffb4c46c78 "derived"

          (gdb) p tab->table->file->table
          $25 = (TABLE *) 0x0
          (gdb) p tab->table
          $27 = (TABLE *) 0x7fffb4c9d078

          So, table->file->multi_range_read_info() is called on a temporary table. The temporary table has handler::table==NULL. This causes a crash in DS-MRR implementation (DS-MRR needs various information from TABLE object, e.g. it needs information about whether a clustered key is present)

          psergei Sergei Petrunia added a comment - (gdb) p tab->table->file->table $25 = (TABLE *) 0x0 (gdb) p tab->table $27 = (TABLE *) 0x7fffb4c9d078 So, table->file->multi_range_read_info() is called on a temporary table. The temporary table has handler::table==NULL. This causes a crash in DS-MRR implementation (DS-MRR needs various information from TABLE object, e.g. it needs information about whether a clustered key is present)

          For regular tables, handler::table is assigned here:

          #0 handler::ha_open
          #1 0x00000000006cfd4b in open_table_from_share
          #2 0x00000000005af7ad in open_table
          #3 0x00000000005b1b91 in open_and_process_table
          #4 0x00000000005b2b8c in open_tables
          ...

          As for the temporary table, it is created by the

          create_tmp_table( .... do_not_open= true, ...)

          call. When do_not_open==true, the table is created but not opened.

          handler::handler() accepts a TABLE_SHARE argument. A temporary table will
          receive a pointer to valid TABLE_SHARE object.

          handler::ha_open will be called for the temporary table from here:

          #0 handler::ha_open
          #1 0x00000000006601fe in open_tmp_table
          #2 0x00000000005e71ea in mysql_derived_create
          #3 0x00000000005e60c2 in mysql_handle_single_derived
          #4 0x0000000000653fcb in st_join_table::preread_init
          #5 0x0000000000662185 in sub_select
          #6 0x00000000006629fd in evaluate_join_record
          #7 0x0000000000662336 in sub_select
          #8 0x0000000000661be7 in do_select

          psergei Sergei Petrunia added a comment - For regular tables, handler::table is assigned here: #0 handler::ha_open #1 0x00000000006cfd4b in open_table_from_share #2 0x00000000005af7ad in open_table #3 0x00000000005b1b91 in open_and_process_table #4 0x00000000005b2b8c in open_tables ... As for the temporary table, it is created by the create_tmp_table( .... do_not_open= true, ...) call. When do_not_open==true, the table is created but not opened. handler::handler() accepts a TABLE_SHARE argument. A temporary table will receive a pointer to valid TABLE_SHARE object. handler::ha_open will be called for the temporary table from here: #0 handler::ha_open #1 0x00000000006601fe in open_tmp_table #2 0x00000000005e71ea in mysql_derived_create #3 0x00000000005e60c2 in mysql_handle_single_derived #4 0x0000000000653fcb in st_join_table::preread_init #5 0x0000000000662185 in sub_select #6 0x00000000006629fd in evaluate_join_record #7 0x0000000000662336 in sub_select #8 0x0000000000661be7 in do_select

          Directions for the solution (not sure if all of them are actually feasible):

          1. Make handler::table be assigned in hander::handler(), not when the table is
          opened.

          2. Make DsMrr_impl::dsmrr_info() only access the TABLE_SHARE, not TABLE object.

          3. Disable DS-MRR for temporary tables (at least, for those that don't have a
          TABLE object yet. This way, tables created with CREATE TEMPORARY TABLE will
          still work).

          psergei Sergei Petrunia added a comment - Directions for the solution (not sure if all of them are actually feasible): 1. Make handler::table be assigned in hander::handler(), not when the table is opened. 2. Make DsMrr_impl::dsmrr_info() only access the TABLE_SHARE, not TABLE object. 3. Disable DS-MRR for temporary tables (at least, for those that don't have a TABLE object yet. This way, tables created with CREATE TEMPORARY TABLE will still work).
          psergei Sergei Petrunia added a comment - The patch is here: http://lists.askmonty.org/pipermail/commits/2013-September/005411.html

          Fix pushed.

          psergei Sergei Petrunia added a comment - Fix pushed.

          People

            psergei Sergei Petrunia
            jb-boin Jean Weisbuch
            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.