Details
-
Bug
-
Status: Closed (View Workflow)
-
Critical
-
Resolution: Fixed
-
11.0(EOL)
-
None
Description
Repeatable on 11.0, not on 10.4-10.11, with Myisam, not Innodb
CREATE TABLE t1 ( a varchar(30) , i int , id int, UNIQUE KEY id (id), KEY (i ,id ,a), KEY (a(1),i)) engine=myisam; |
|
INSERT INTO t1 VALUES('fej',NULL,1),('jeyw',8,2),(NULL,181,3),('wrkovd',9,4),('',NULL,5),('ko',NULL,6),('vdgzyxkop',217,7),('',7,8),('zy',0,9),('yxkopv',8,10),('kopv',1,11),('opv',4,12),('vc',9,13),('ri',1,14),('tkcn',1,15),('cnm',6,16),('m',0,17),('d',9,18),('e',28,19),(NULL,0,20); |
|
SELECT i, MAX( id ) FROM t1 |
WHERE ( a IS NULL OR a IN ('o','h') ) AND ( id BETWEEN 6 AND 7 OR id IN ( 8, 1) ) |
GROUP BY i; |
Version: '11.0.2-MariaDB-debug-log'
|
mariadbd: /11.0/src/sql/sql_select.cc:24092: int join_read_first(JOIN_TAB*): Assertion `table->no_keyread || !table->covering_keys.is_set(tab->index) || table->file->keyread == tab->index' failed.
|
230328 14:15:23 [ERROR] mysqld got signal 6 ;
|
|
Server version: 11.0.2-MariaDB-debug-log source revision: 6c3b1dced41c238f814aeabbc725e31c3106c0f4
|
|
??:0(gsignal)[0x7fc82b8b100b]
|
??:0(abort)[0x7fc82b890859]
|
/lib/x86_64-linux-gnu/libc.so.6(+0x22729)[0x7fc82b890729]
|
??:0(__assert_fail)[0x7fc82b8a1fd6]
|
sql/sql_select.cc:24095(join_read_first(st_join_table*))[0x561e247410f9]
|
sql/sql_select.cc:23033(sub_select(JOIN*, st_join_table*, bool))[0x561e247393f9]
|
sql/sql_select.cc:22568(do_select(JOIN*, Procedure*))[0x561e24737336]
|
sql/sql_select.cc:4895(JOIN::exec_inner())[0x561e246b8157]
|
sql/sql_select.cc:4672(JOIN::exec())[0x561e246b5508]
|
sql/sql_select.cc:5153(mysql_select(THD*, TABLE_LIST*, List<Item>&, Item*, unsigned int, st_order*, st_order*, Item*, st_order*, unsigned long long, select_result*, st_select_lex_unit*, st_select_lex*))[0x561e246b9c16]
|
sql/sql_select.cc:611(handle_select(THD*, LEX*, select_result*, unsigned long long))[0x561e24689819]
|
sql/sql_parse.cc:6267(execute_sqlcom_select(THD*, TABLE_LIST*))[0x561e245abac5]
|
sql/sql_parse.cc:3949(mysql_execute_command(THD*, bool))[0x561e2459a374]
|
sql/sql_parse.cc:7999(mysql_parse(THD*, char*, unsigned int, Parser_state*))[0x561e245b6848]
|
sql/sql_parse.cc:1896(dispatch_command(enum_server_command, THD*, char*, unsigned int, bool))[0x561e2458ca9e]
|
sql/sql_parse.cc:1407(do_command(THD*, bool))[0x561e245897da]
|
sql/sql_connect.cc:1416(do_handle_one_connection(CONNECT*, bool))[0x561e24a56c33]
|
sql/sql_connect.cc:1320(handle_one_connection)[0x561e24a56590]
|
perfschema/pfs.cc:2203(pfs_spawn_thread)[0x561e2566fcd8]
|
nptl/pthread_create.c:478(start_thread)[0x7fc82bdbc609]
|
|
Query (0x6290001092a8): SELECT i, MAX( id ) FROM t1
|
WHERE ( a IS NULL OR a IN ('o','h') ) AND ( id BETWEEN 6 AND 7 OR id IN ( 8, 1) )
|
GROUP BY i
|
also 11.0/src/sql/sql_select.cc:24131: int join_read_last(JOIN_TAB*): Assertion `table->no_keyread || !table->covering_keys.is_set(tab->index) || table->file->keyread == tab->index'
assert failure in sub_select()
error= (*join_tab->read_first_record)(join_tab);
table->file->keyread == tab->index
something is altering keyread when the table is MyISAM, not InnoDB
The optimizer, when testing for rowid_filters
best_access_path()/apply_filter()
{
filter= table->best_range_rowid_filter(key_no,
rows2double(range->rows),
file->cost(&tmp),
file->cost(tmp.index_cost),
record_count,
&records_best_filter);
set_if_smaller(best.records_out, records_best_filter);
{
filter= filter->apply_filter(thd, table, &tmp,
&records_after_filter,
&startup_cost,
range->ranges,
record_count);
...
decides that when using MyISAM, a rowid filter is faster than not using one.
When using InnoDB, the costs are slightly different and it chooses NOT to include a rowid filter.
Filling the rowid filter object container
sub_select()/build_range_rowid_filter()
{
{
join_tab->build_range_rowid_filter();
...
ends up calling Range_rowid_filter::fill()
quick->range_end();
file->ha_end_keyread();
ha_end_keyread() sets file->keyread to MAX_KEY
back up the stack, in sub_select(), a subsequent call
{
error= (*join_tab->read_first_record)(join_tab);
executes the assert
DBUG_ASSERT(table->no_keyread ||
!table->covering_keys.is_set(tab->index) ||
table->file->keyread == tab->index);
each element of which, in this case will be false.
The obvious solution is reset the keyread variable back to it's state as at the start of the Range_rowid_filter::fill() routine, like other similar table/file variables.
rowid filters are evaluated in Range_rowid_filter_cost_info::apply_filter()
org_cost= (file->cost_for_reading_multiple_times(prev_records,
cost) +
records * tmp);
new_cost= (file->cost_for_reading_multiple_times(prev_records,
&adjusted_cost) +
new_records * tmp + filter_startup_cost);
Any scenario where new_cost < org_cost, will lead to a rowid filter being constructed and used.