MDEV-20867 - Perform careful review of "Server crashes with BACKUP STAGE and FLUSH TABLE table_name"

Reverted original patch (c2e0a0b).

For consistency with "LOCK TABLE <table_name> READ" and "FLUSH TABLES
WITH READ LOCK", which are forbidden under "BACKUP STAGE", forbid "FLUSH
TABLE <table_name> FOR EXPORT" and "FLUSH TABLE <table_name> WITH READ
LOCK" as well.

It'd allow consistent fixes for problems like MDEV-18643.
This commit is contained in:
Sergey Vojtovich 2019-11-01 19:18:47 +04:00
parent 646d1ec83a
commit c5e00fea10
5 changed files with 16 additions and 53 deletions

View File

@ -521,26 +521,8 @@ BACKUP STAGE END;
CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, f INT); CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, f INT);
BACKUP STAGE START; BACKUP STAGE START;
FLUSH TABLE t1 FOR EXPORT; FLUSH TABLE t1 FOR EXPORT;
UNLOCK TABLES; ERROR HY000: Can't execute the command as you have a BACKUP STAGE active
BACKUP STAGE END; FLUSH TABLE t1 WITH READ LOCK;
DROP TABLE t1; ERROR HY000: Can't execute the command as you have a BACKUP STAGE active
CREATE TABLE t1 (a INT);
BACKUP STAGE START;
FLUSH TABLE t1 FOR EXPORT;
UNLOCK TABLES;
connect con1,localhost,root,,test;
BACKUP STAGE START;
connection default;
BACKUP STAGE END;
connection con1;
BACKUP STAGE END;
disconnect con1;
connection default;
DROP TABLE t1;
CREATE TABLE t1 (a INT);
BACKUP STAGE START;
FLUSH TABLES t1 WITH READ LOCK;
UNLOCK TABLES;
BACKUP STAGE BLOCK_COMMIT;
BACKUP STAGE END; BACKUP STAGE END;
DROP TABLE t1; DROP TABLE t1;

View File

@ -509,30 +509,9 @@ BACKUP STAGE END;
CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, f INT); CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, f INT);
BACKUP STAGE START; BACKUP STAGE START;
--error ER_BACKUP_LOCK_IS_ACTIVE
FLUSH TABLE t1 FOR EXPORT; FLUSH TABLE t1 FOR EXPORT;
UNLOCK TABLES; --error ER_BACKUP_LOCK_IS_ACTIVE
BACKUP STAGE END; FLUSH TABLE t1 WITH READ LOCK;
DROP TABLE t1;
CREATE TABLE t1 (a INT);
BACKUP STAGE START;
FLUSH TABLE t1 FOR EXPORT;
UNLOCK TABLES;
--connect (con1,localhost,root,,test)
--send BACKUP STAGE START
--connection default
BACKUP STAGE END;
--connection con1
reap;
BACKUP STAGE END;
--disconnect con1
--connection default
DROP TABLE t1;
CREATE TABLE t1 (a INT);
BACKUP STAGE START;
FLUSH TABLES t1 WITH READ LOCK;
UNLOCK TABLES;
BACKUP STAGE BLOCK_COMMIT;
BACKUP STAGE END; BACKUP STAGE END;
DROP TABLE t1; DROP TABLE t1;

View File

@ -3166,20 +3166,15 @@ void MDL_context::set_transaction_duration_for_all_locks()
DBUG_ASSERT(m_tickets[MDL_STATEMENT].is_empty()); DBUG_ASSERT(m_tickets[MDL_STATEMENT].is_empty());
/* Don't swap locks if this thread is running backup stages */
if (current_thd->current_backup_stage == BACKUP_FINISHED)
m_tickets[MDL_TRANSACTION].swap(m_tickets[MDL_EXPLICIT]); m_tickets[MDL_TRANSACTION].swap(m_tickets[MDL_EXPLICIT]);
Ticket_iterator it_ticket(m_tickets[MDL_EXPLICIT]); Ticket_iterator it_ticket(m_tickets[MDL_EXPLICIT]);
while ((ticket= it_ticket++)) while ((ticket= it_ticket++))
{
if (ticket->get_key()->mdl_namespace() != MDL_key::BACKUP)
{ {
m_tickets[MDL_EXPLICIT].remove(ticket); m_tickets[MDL_EXPLICIT].remove(ticket);
m_tickets[MDL_TRANSACTION].push_front(ticket); m_tickets[MDL_TRANSACTION].push_front(ticket);
} }
}
#ifndef DBUG_OFF #ifndef DBUG_OFF
Ticket_iterator trans_it(m_tickets[MDL_TRANSACTION]); Ticket_iterator trans_it(m_tickets[MDL_TRANSACTION]);

View File

@ -5580,6 +5580,7 @@ void THD::leave_locked_tables_mode()
{ {
if (locked_tables_mode == LTM_LOCK_TABLES) if (locked_tables_mode == LTM_LOCK_TABLES)
{ {
DBUG_ASSERT(current_backup_stage == BACKUP_FINISHED);
/* /*
When leaving LOCK TABLES mode we have to change the duration of most When leaving LOCK TABLES mode we have to change the duration of most
of the metadata locks being held, except for HANDLER and GRL locks, of the metadata locks being held, except for HANDLER and GRL locks,

View File

@ -525,6 +525,12 @@ bool flush_tables_with_read_lock(THD *thd, TABLE_LIST *all_tables)
goto error; goto error;
} }
if (thd->current_backup_stage != BACKUP_FINISHED)
{
my_error(ER_BACKUP_LOCK_IS_ACTIVE, MYF(0));
return true;
}
if (thd->lex->type & REFRESH_READ_LOCK) if (thd->lex->type & REFRESH_READ_LOCK)
{ {
/* /*