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

    • Type: Bug
    • Status: Closed
    • Priority: Critical
    • Resolution: Fixed
    • Affects Version/s: 5.5.32, 5.5.33
    • Fix Version/s: 5.5.34
    • Component/s: None
    • Labels:
    • Environment:
      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

        Gliffy Diagrams

          Attachments

            Activity

            Hide
            psergey 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"

            Show
            psergey 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"
            Hide
            psergey 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)

            Show
            psergey 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)
            Hide
            psergey 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

            Show
            psergey 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
            Hide
            psergey 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).

            Show
            psergey 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).
            Show
            psergey Sergei Petrunia added a comment - The patch is here: http://lists.askmonty.org/pipermail/commits/2013-September/005411.html
            Hide
            psergey Sergei Petrunia added a comment -

            Fix pushed.

            Show
            psergey Sergei Petrunia added a comment - Fix pushed.

              People

              • Assignee:
                psergey Sergei Petrunia
                Reporter:
                jb-boin Jean Weisbuch
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: