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

Assertion `partial_join_cost >= -2.2204460492503131e-16' failed in recompute_join_cost_with_limit on SELECT

    XMLWordPrintable

Details

    Description

      Further to MDEV-36096, the assert changed there is still reachable. The new bound is a fixed number, but the rounding residue it has to cover grows with the cost.

      --source include/have_innodb.inc
       
      CREATE TABLE t (c INT NOT NULL UNIQUE) ENGINE=InnoDB;
      INSERT INTO t VALUES (0),(1),(2),(3),(4),(5);
       
      SET optimizer_scan_setup_cost=100000000;
      SET optimizer_join_limit_pref_ratio=1;
      EXPLAIN SELECT c FROM t ORDER BY c LIMIT 1;
      SET optimizer_join_limit_pref_ratio= DEFAULT;
      SET optimizer_scan_setup_cost= DEFAULT;
       
      DROP TABLE t;
      

      Leads to:

      CS 13.1.0 da18481158c81ca94689702073c3e04aad85a6a3 (Debug, UBASAN, Clang 22.1.8-20260622) Build 22/09/2026, with the MDEV-36096 patch applied

      mariadbd: sql/sql_select.cc:11916: double recompute_join_cost_with_limit(const JOIN *, bool, double *, double): Assertion `partial_join_cost >= -2.2204460492503131e-16' failed.
      

      CS 13.1.0 da18481158c81ca94689702073c3e04aad85a6a3 (Debug, UBASAN, Clang 22.1.8-20260622) Build 22/09/2026, with the MDEV-36096 patch applied

      #0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>)at ./nptl/pthread_kill.c:44
      #1  __pthread_kill_internal (signo=6, threadid=<optimized out>)at ./nptl/pthread_kill.c:78
      #2  __GI___pthread_kill (threadid=<optimized out>, signo=6)at ./nptl/pthread_kill.c:89
      #3  0x000061039347dbe6 in handle_fatal_signal (sig=<optimized out>)at sql/signal_handler.cc:298
      #4  <signal handler called>
      #5  __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>)at ./nptl/pthread_kill.c:44
      #6  __pthread_kill_internal (signo=6, threadid=<optimized out>)at ./nptl/pthread_kill.c:78
      #7  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6)at ./nptl/pthread_kill.c:89
      #8  0x00007a769984527e in __GI_raise (sig=sig@entry=6)at ../sysdeps/posix/raise.c:26
      #9  0x00007a76998288ff in __GI_abort () at ./stdlib/abort.c:79
      #10 0x00007a769982881b in __assert_fail_base (fmt=0x7a76999d1208 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0x610392054620 <str> "partial_join_cost >= -2.2204460492503131e-16", file=file@entry=0x61039204aa74 "sql/sql_select.cc", line=line@entry=11916, function=function@entry=0x610392054680 <__PRETTY_FUNCTION__._Z30recompute_join_cost_with_limitPK4JOINbPdd> "double recompute_join_cost_with_limit(const JOIN *, bool, double *, double)") at ./assert/assert.c:96
      #11 0x00007a769983b517 in __assert_fail (assertion=0x610392054620 <str> "partial_join_cost >= -2.2204460492503131e-16", file=0x61039204aa74 "sql/sql_select.cc", line=11916, function=0x610392054680 <__PRETTY_FUNCTION__._Z30recompute_join_cost_with_limitPK4JOINbPdd> "double recompute_join_cost_with_limit(const JOIN *, bool, double *, double)") at ./assert/assert.c:105
      #12 0x0000610393fb5b6f in recompute_join_cost_with_limit (join=join@entry=0x794698b5e828, skip_sorting=<optimized out>, first_table_cost=first_table_cost@entry=0x6e7599d016b0, fraction=<optimized out>)at sql/sql_select.cc:11916
      #13 0x0000610393fabbb7 in join_limit_shortcut_finalize_plan (join=0x794698b5e828, cost=<optimized out>)at sql/sql_select.cc:11988
      #14 0x0000610393fa7f62 in choose_plan (join=0x794698b5e828, join_tables=<optimized out>, emb_sjm_nest=<optimized out>)at sql/sql_select.cc:10391
      #15 0x0000610393f1bb03 in make_join_statistics (join=0x794698b5e828, tables_list=<optimized out>, keyuse_array=<optimized out>)at sql/sql_select.cc:6382
      #16 0x0000610393ef38a9 in JOIN::optimize_inner (this=0x794698b5e828)at sql/sql_select.cc:2764
      #17 0x0000610393eecfd7 in JOIN::optimize (this=<optimized out>)at sql/sql_select.cc:2017
      #18 0x0000610393ecbf9b in mysql_select (thd=0x793698b90220, tables=<optimized out>, fields=<optimized out>, conds=<optimized out>, og_num=<optimized out>, order=<optimized out>, group=0x0, having=0x0, proc_param=0x0, select_options=<optimized out>, result=0x794698b5df80, unit=0x793698b947b8, select_lex=0x794698b5c518)at sql/sql_select.cc:5426
      #19 0x0000610394049310 in mysql_explain_union (thd=<optimized out>, unit=0x793698b947b8, result=<optimized out>)at sql/sql_select.cc:31992
      #20 0x0000610393d61ef8 in execute_sqlcom_select (thd=0x793698b90220, all_tables=<optimized out>)at sql/sql_parse.cc:6168
      #21 0x0000610393d4cffd in mysql_execute_command (thd=0x793698b90220, is_called_from_prepared_stmt=<optimized out>)at sql/sql_parse.cc:3997
      #22 0x0000610393d26c5b in mysql_parse (thd=thd@entry=0x793698b90220, rawbuf=<optimized out>, length=<optimized out>, parser_state=<optimized out>)at sql/sql_parse.cc:7968
      #23 0x0000610393d1ec3f in dispatch_command (command=<optimized out>, thd=0x793698b90220, packet=<optimized out>, packet_length=<optimized out>, blocking=<optimized out>)at sql/sql_parse.cc:1903
      #24 0x0000610393d29047 in do_command (thd=thd@entry=0x793698b90220, blocking=<optimized out>)at sql/sql_parse.cc:1437
      #25 0x000061039456906d in do_handle_one_connection (connect=<optimized out>, connect@entry=0x7726989e3d90, put_in_cache=<optimized out>)at sql/sql_connect.cc:1514
      #26 0x0000610394568b96 in handle_one_connection (arg=0x7726989e3d90)at sql/sql_connect.cc:1426
      #27 0x00007a769a148e17 in asan_thread_start ()
      #28 0x00007a769989cb84 in start_thread (arg=<optimized out>)at ./nptl/pthread_create.c:447
      

      The same happens with no cost variable set, on a table large enough to carry the cost. This one aborted on 4 of 5 runs, the row estimate decides:

      --source include/have_innodb.inc
      --source include/have_sequence.inc
       
      CREATE TABLE t (c INT NOT NULL UNIQUE) ENGINE=InnoDB;
      INSERT INTO t SELECT seq FROM seq_1_to_100000;
       
      SET optimizer_join_limit_pref_ratio=1;
      --disable_result_log
      EXPLAIN SELECT c FROM t ORDER BY c LIMIT 28000;
      --enable_result_log
      SET optimizer_join_limit_pref_ratio= DEFAULT;
       
      DROP TABLE t;
      

      Setup (please take note):

      Compiled with Clang (22.1.8 here) with:
          -DWITH_ASAN=ON -DWITH_ASAN_SCOPE=ON -DWITH_UBSAN=ON -DWSREP_LIB_WITH_ASAN=ON
          -DCMAKE_C{,XX}_FLAGS='-O1 -march=native'
       
      The -march=native matters. It gives Clang an FMA instruction, and the fused
      multiply-add is what leaves the negative value behind. A build of the same
      source without it does not abort.
      

      Attachments

        Issue Links

          Activity

            People

              bsrikanth Srikanth Bondalapati
              Roel Roel Van de Paar
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:

                Time Tracking

                  Estimated:
                  Original Estimate - 0d
                  0d
                  Remaining:
                  Time Spent - 1.25h Remaining Estimate - 1.5d
                  1.5d
                  Logged:
                  Time Spent - 1.25h Remaining Estimate - 1.5d
                  1.25h

                  Git Integration

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