Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions mysql-test/suite/gcol/r/innodb_virtual_basic.result
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ INSERT INTO t VALUES (1290, 212, DEFAULT, "xmx");
ROLLBACK;
SELECT c FROM t;
c
NULL
13
29
NULL
SELECT * FROM t;
a b c h
10 3 13 mm
Expand Down Expand Up @@ -303,23 +303,23 @@ END|
CALL UPDATE_t();
SELECT c FROM t;
c
NULL
19
29
2103
29
NULL
CALL DELETE_insert_t();
SELECT c FROM t;
c
NULL
19
29
2103
29
NULL
DROP INDEX idx ON t;
CALL UPDATE_t();
SELECT c FROM t;
c
2103
19
2103
29
NULL
DROP PROCEDURE DELETE_insert_t;
Expand Down Expand Up @@ -523,10 +523,10 @@ UPDATE t SET h = "e" WHERE h="a";
ROLLBACK;
SELECT a, c, h FROM t;
a c h
NULL NULL d
11 14 a
18 19 b
28 29 c
NULL NULL d
DROP TABLE t;
CREATE TABLE `t1` (
`col1` int(11) NOT NULL,
Expand Down
5 changes: 5 additions & 0 deletions mysql-test/suite/gcol/t/innodb_virtual_basic.test
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ INSERT INTO t VALUES (128, 22, DEFAULT, "xx");
INSERT INTO t VALUES (1290, 212, DEFAULT, "xmx");
ROLLBACK;

--sorted_result
SELECT c FROM t;
SELECT * FROM t;

Expand Down Expand Up @@ -356,13 +357,16 @@ END|
delimiter ;|

CALL UPDATE_t();
--sorted_result
SELECT c FROM t;

CALL DELETE_insert_t();
--sorted_result
SELECT c FROM t;

DROP INDEX idx ON t;
CALL UPDATE_t();
--sorted_result
SELECT c FROM t;

DROP PROCEDURE DELETE_insert_t;
Expand Down Expand Up @@ -537,6 +541,7 @@ START TRANSACTION;
UPDATE t SET m =10 WHERE m = 1;
UPDATE t SET h = "e" WHERE h="a";
ROLLBACK;
--sorted_result
SELECT a, c, h FROM t;

DROP TABLE t;
Expand Down
14 changes: 14 additions & 0 deletions mysql-test/suite/vcol/r/races.result
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,17 @@ disconnect con1;
connection default;
drop table t1;
set debug_sync='reset';
#
# MDEV-39261 MariaDB crash on startup in presence of
# indexed virtual columns
#
# Create 33 tables with virtual index
InnoDB 0 transactions not purged
connect purge_control,localhost,root;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection default;
# Do update on all 33 tables
# restart: --innodb_purge_threads=1 --debug_dbug=d,ib_purge_virtual_index_callback
InnoDB 0 transactions not purged
# Drop all 33 tables
# restart
56 changes: 56 additions & 0 deletions mysql-test/suite/vcol/t/races.test
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,59 @@ disconnect con1;
connection default;
drop table t1;
set debug_sync='reset';

--echo #
--echo # MDEV-39261 MariaDB crash on startup in presence of
--echo # indexed virtual columns
--echo #
# To make purge thread to work on multiple tables on the same batch,
# we need 33 tables because there are 32 pre-existing purge_node exists.

--echo # Create 33 tables with virtual index
--disable_query_log
let $i = 33;
while ($i)
{
eval CREATE TABLE t$i(
a INT PRIMARY KEY,
b INT DEFAULT 1, INDEX(b),
c INT GENERATED ALWAYS AS (a + b) VIRTUAL,
INDEX(c)
) ENGINE=InnoDB;
eval INSERT INTO t$i(a) VALUES(1);
dec $i;
}
--enable_query_log
--source ../../innodb/include/wait_all_purged.inc
--connect purge_control,localhost,root
START TRANSACTION WITH CONSISTENT SNAPSHOT;

--connection default
--echo # Do update on all 33 tables
--disable_query_log
let $i = 33;
while ($i)
{
eval UPDATE t$i SET b = 11 WHERE a = 1;
dec $i;
}
--enable_query_log

let $shutdown_timeout=0;
let $restart_parameters=--innodb_purge_threads=1 --debug_dbug=d,ib_purge_virtual_index_callback;
--source include/restart_mysqld.inc
--source ../../innodb/include/wait_all_purged.inc

--echo # Drop all 33 tables
--disable_query_log
let $i = 33;
while ($i)
{
eval DROP TABLE t$i;
dec $i;
}
--enable_query_log

let $restart_parameters=;
let $shutdown_timeout=;
--source include/restart_mysqld.inc
2 changes: 1 addition & 1 deletion sql/sql_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@ static inline bool check_field_pointers(const TABLE *table)
leave prelocked mode if needed.
*/

int close_thread_tables(THD *thd)
int close_thread_tables(THD *thd) noexcept
{
TABLE *table;
int error= 0;
Expand Down
2 changes: 1 addition & 1 deletion sql/sql_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
TABLE_LIST *TABLE_LIST::*link,
const LEX_CSTRING *db_name,
const LEX_CSTRING *table_name);
int close_thread_tables(THD *thd);
int close_thread_tables(THD *thd) noexcept;
void switch_to_nullable_trigger_fields(List<Item> &items, TABLE *);
void switch_defaults_to_nullable_trigger_fields(TABLE *table);
bool fill_record_n_invoke_before_triggers(THD *thd, TABLE *table,
Expand Down
12 changes: 3 additions & 9 deletions sql/sql_class.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5024,10 +5024,10 @@ extern "C" const char *thd_priv_user(MYSQL_THD thd, size_t *length)
have only one table open at any given time.
*/
TABLE *open_purge_table(THD *thd, const char *db, size_t dblen,
const char *tb, size_t tblen)
const char *tb, size_t tblen,
MDL_ticket *mdl_ticket) noexcept
{
DBUG_ENTER("open_purge_table");
DBUG_ASSERT(thd->open_tables == NULL);
DBUG_ASSERT(thd->locked_tables_mode < LTM_PRELOCKED);

/* Purge already hold the MDL for the table */
Expand All @@ -5038,6 +5038,7 @@ TABLE *open_purge_table(THD *thd, const char *db, size_t dblen,

tl->init_one_table(&db_name, &table_name, 0, TL_READ);
tl->i_s_requested_object= OPEN_TABLE_ONLY;
tl->mdl_request.ticket= mdl_ticket;

bool error= open_table(thd, tl, &ot_ctx);

Expand All @@ -5050,13 +5051,6 @@ TABLE *open_purge_table(THD *thd, const char *db, size_t dblen,
DBUG_RETURN(error ? NULL : tl->table);
}

TABLE *get_purge_table(THD *thd)
{
/* see above, at most one table can be opened */
DBUG_ASSERT(thd->open_tables == NULL || thd->open_tables->next == NULL);
return thd->open_tables;
}

/** Find an open table in the list of prelocked tabled

Used for foreign key actions, for example, in UPDATE t1 SET a=1;
Expand Down
4 changes: 2 additions & 2 deletions storage/innobase/dict/dict0dict.cc
Original file line number Diff line number Diff line change
Expand Up @@ -626,13 +626,13 @@ bool dict_table_t::parse_name(char (&db_name)[NAME_LEN + 1],
dict_sys.unfreeze();

*db_name_len= filename_to_tablename(db_buf, db_name,
MAX_DATABASE_NAME_LEN + 1, true);
NAME_LEN + 1, true);

if (is_temp)
return false;

*tbl_name_len= filename_to_tablename(tbl_buf, tbl_name,
MAX_TABLE_NAME_LEN + 1, true);
NAME_LEN + 1, true);
return true;
}

Expand Down
44 changes: 21 additions & 23 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,10 @@ TABLE *find_fk_open_table(THD *thd, const char *db, size_t db_len,
const char *table, size_t table_len);
MYSQL_THD create_background_thd();
void reset_thd(MYSQL_THD thd);
TABLE *get_purge_table(THD *thd);
TABLE *open_purge_table(THD *thd, const char *db, size_t dblen,
const char *tb, size_t tblen);
void close_thread_tables(THD* thd);
const char *tb, size_t tblen,
MDL_ticket *mdl_ticket) noexcept;
int close_thread_tables(THD* thd) noexcept;

#ifdef MYSQL_DYNAMIC_PLUGIN
#define tc_size 400
Expand Down Expand Up @@ -8536,7 +8536,7 @@ ATTRIBUTE_COLD bool wsrep_append_table_key(MYSQL_THD thd, const dict_table_t &ta
{
char db_buf[NAME_LEN + 1];
char tbl_buf[NAME_LEN + 1];
ulint db_buf_len, tbl_buf_len;
size_t db_buf_len, tbl_buf_len;

if (!table.parse_name(db_buf, tbl_buf, &db_buf_len, &tbl_buf_len))
{
Expand Down Expand Up @@ -20071,33 +20071,18 @@ ha_innobase::multi_range_read_explain_info(
for purge thread */
static TABLE* innodb_find_table_for_vc(THD* thd, dict_table_t* table)
{
TABLE *mysql_table;
const bool bg_thread = THDVAR(thd, background_thread);

if (bg_thread) {
if ((mysql_table = get_purge_table(thd))) {
return mysql_table;
}
} else {
if (table->vc_templ->mysql_table_query_id
== thd_get_query_id(thd)) {
return table->vc_templ->mysql_table;
}
if (table->vc_templ->mysql_table_query_id == thd_get_query_id(thd)) {
return table->vc_templ->mysql_table;
}

TABLE *mysql_table;
char db_buf[NAME_LEN + 1];
char tbl_buf[NAME_LEN + 1];
ulint db_buf_len, tbl_buf_len;
size_t db_buf_len, tbl_buf_len;

if (!table->parse_name(db_buf, tbl_buf, &db_buf_len, &tbl_buf_len)) {
return NULL;
}

if (bg_thread) {
return open_purge_table(thd, db_buf, db_buf_len,
tbl_buf, tbl_buf_len);
}

mysql_table = find_fk_open_table(thd, db_buf, db_buf_len,
tbl_buf, tbl_buf_len);
table->vc_templ->mysql_table = mysql_table;
Expand Down Expand Up @@ -21306,3 +21291,16 @@ void alter_stats_rebuild(dict_table_t *table, THD *thd)
" table rebuild: %s", ut_strerr(ret));
DBUG_VOID_RETURN;
}

TABLE* innobase_open_purge_table(THD *thd, const char *db_buf,
size_t db_len, const char *tbl_buf,
size_t tbl_len,
MDL_ticket *mdl_ticket) noexcept
{
return open_purge_table(thd, db_buf, db_len, tbl_buf, tbl_len, mdl_ticket);
}

int innobase_close_thread_tables(THD *thd) noexcept
{
return close_thread_tables(thd);
}
12 changes: 12 additions & 0 deletions storage/innobase/include/dict0mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -2551,6 +2551,18 @@ struct dict_table_t {
static dict_table_t *create(const span<const char> &name, fil_space_t *space,
ulint n_cols, ulint n_v_cols, ulint flags,
ulint flags2);

/** @return whether the table has any indexed virtual column */
bool has_virtual_index() const
{
for (dict_index_t *index = indexes.start;
index; index = UT_LIST_GET_NEXT(indexes, index))
{
if (index->has_virtual())
return true;
}
return false;
}
};

inline void dict_index_t::set_modified(mtr_t& mtr) const
Expand Down
21 changes: 21 additions & 0 deletions storage/innobase/include/row0mysql.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Created 9/17/2000 Heikki Tuuri
struct row_prebuilt_t;
class ha_innobase;
class ha_handler_stats;
class MDL_ticket;

/*******************************************************************//**
Frees the blob heap in prebuilt when no longer needed. */
Expand Down Expand Up @@ -830,6 +831,26 @@ void
innobase_rename_vc_templ(
dict_table_t* table);

/** Open a table for purge operations with MariaDB TABLE handle.
This is a wrapper to make open_purge_table() accessible from InnoDB
purge subsystem.
@param thd thread handle
@param db_buf database name buffer
@param db_len database name length
@param tbl_buf table name buffer
@param tbl_len table name length
@return MariaDB TABLE handle, or NULL if not opened */
TABLE* innobase_open_purge_table(THD *thd, const char *db_buf,
size_t db_len, const char *tbl_buf,
size_t tbl_len,
MDL_ticket *mdl_ticket) noexcept;

/** Close all tables opened by the thread.
This is a wrapper to make close_thread_tables() accessible from
InnoDB purge subsytem.
@param thd thread handle */
int innobase_close_thread_tables(THD *thd) noexcept;

#define ROW_PREBUILT_FETCH_MAGIC_N 465765687

#define ROW_MYSQL_WHOLE_ROW 0
Expand Down
Loading