mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
MDEV-24929 Server crash in thr_multi_unlock or in get_schema_tables_result
This was caused by two different bugs: 1) Information_schema tables where not locked by lock_tables, but get_lock_data() was not filtering these out. This caused a crash when mysql_unlock_some_tables() tried to unlock tables early, including not locked information schema tables. Fixed by not locking SYSTEM_TMP_TABLES 2) In some cases the optimizer will notice that we do not need to read the information_schema tables at all. In this case join_tab->read_record is not set, which caused a crash in get_schema_tables_result() Fixed by ignoring const tables in get_schema_tables_result()
This commit is contained in:
parent
0ab1e3914c
commit
640f42311a
4 changed files with 43 additions and 7 deletions
|
@ -2303,5 +2303,18 @@ group by f;
|
|||
f
|
||||
drop table t1;
|
||||
#
|
||||
# MDEV-24929 Server crash in thr_multi_unlock or in
|
||||
# get_schema_tables_result upon select from I_S with joins
|
||||
#
|
||||
CREATE TABLE t1 (a TIMESTAMP, KEY (a));
|
||||
INSERT INTO t1 VALUES ('2012-12-12'),('2021-11-11');
|
||||
SELECT count(*) FROM t1 AS t1a LEFT JOIN (t1 AS t1b JOIN INFORMATION_SCHEMA.ROUTINES) ON (t1b.a IS NULL);
|
||||
count(*)
|
||||
2
|
||||
SELECT count(*) FROM t1 AS t1a LEFT JOIN (t1 AS t1b JOIN INFORMATION_SCHEMA.PROFILING) ON (t1b.a IS NULL);
|
||||
count(*)
|
||||
2
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.3 tests
|
||||
#
|
||||
|
|
|
@ -2034,6 +2034,16 @@ inner join t1 on f=i.column_name
|
|||
group by f;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-24929 Server crash in thr_multi_unlock or in
|
||||
--echo # get_schema_tables_result upon select from I_S with joins
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a TIMESTAMP, KEY (a));
|
||||
INSERT INTO t1 VALUES ('2012-12-12'),('2021-11-11');
|
||||
SELECT count(*) FROM t1 AS t1a LEFT JOIN (t1 AS t1b JOIN INFORMATION_SCHEMA.ROUTINES) ON (t1b.a IS NULL);
|
||||
SELECT count(*) FROM t1 AS t1a LEFT JOIN (t1 AS t1b JOIN INFORMATION_SCHEMA.PROFILING) ON (t1b.a IS NULL);
|
||||
DROP TABLE t1;
|
||||
--echo #
|
||||
--echo # End of 10.3 tests
|
||||
--echo #
|
||||
|
|
17
sql/lock.cc
17
sql/lock.cc
|
@ -727,6 +727,9 @@ static int unlock_external(THD *thd, TABLE **table,uint count)
|
|||
- GET_LOCK_STORE_LOCKS : Store lock info in TABLE
|
||||
- GET_LOCK_SKIP_SEQUENCES : Ignore sequences (for temporary unlock)
|
||||
- GET_LOCK_ON_THD : Store lock in thd->mem_root
|
||||
|
||||
Temporary tables are not locked (as these are single user), except for
|
||||
TRANSACTIONAL_TMP_TABLES as locking is needed to handle transactions.
|
||||
*/
|
||||
|
||||
MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
|
||||
|
@ -743,8 +746,8 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
|
|||
{
|
||||
TABLE *t= table_ptr[i];
|
||||
|
||||
if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE &&
|
||||
t->s->tmp_table != INTERNAL_TMP_TABLE &&
|
||||
if ((likely(!t->s->tmp_table) ||
|
||||
(t->s->tmp_table == TRANSACTIONAL_TMP_TABLE)) &&
|
||||
(!(flags & GET_LOCK_SKIP_SEQUENCES) || t->s->sequence == 0))
|
||||
{
|
||||
lock_count+= t->file->lock_count();
|
||||
|
@ -772,13 +775,13 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
|
|||
|
||||
for (i=0 ; i < count ; i++)
|
||||
{
|
||||
TABLE *table;
|
||||
TABLE *table= table_ptr[i];
|
||||
enum thr_lock_type lock_type;
|
||||
THR_LOCK_DATA **locks_start;
|
||||
table= table_ptr[i];
|
||||
if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE ||
|
||||
table->s->tmp_table == INTERNAL_TMP_TABLE ||
|
||||
((flags & GET_LOCK_SKIP_SEQUENCES) && table->s->sequence))
|
||||
|
||||
if (!((likely(!table->s->tmp_table) ||
|
||||
(table->s->tmp_table == TRANSACTIONAL_TMP_TABLE)) &&
|
||||
(!(flags & GET_LOCK_SKIP_SEQUENCES) || table->s->sequence == 0)))
|
||||
continue;
|
||||
lock_type= table->reginfo.lock_type;
|
||||
DBUG_ASSERT(lock_type != TL_WRITE_DEFAULT && lock_type != TL_READ_DEFAULT);
|
||||
|
|
|
@ -8837,6 +8837,16 @@ bool get_schema_tables_result(JOIN *join,
|
|||
if (table_list->schema_table->fill_table == 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
Do not fill in tables thare are marked as JT_CONST as these will never
|
||||
be read and they also don't have a tab->read_record.table set!
|
||||
This can happen with queries like
|
||||
SELECT * FROM t1 LEFT JOIN (t1 AS t1b JOIN INFORMATION_SCHEMA.ROUTINES)
|
||||
ON (t1b.a IS NULL);
|
||||
*/
|
||||
if (tab->type == JT_CONST)
|
||||
continue;
|
||||
|
||||
/* skip I_S optimizations specific to get_all_tables */
|
||||
if (lex->describe &&
|
||||
(table_list->schema_table->fill_table != get_all_tables))
|
||||
|
|
Loading…
Reference in a new issue