Commit 621501f3 authored by Monty's avatar Monty

MDEV-25606: Concurrent CREATE TRIGGER statements mix up in binlog and break replication

The bug is that we don't have a a lock on the trigger name, so it is
possible for two threads to try to create the same trigger at the same
time and both thinks that they have succeed.
Same thing can happen with drop trigger or a combinations of create and
drop trigger.

Fixed by adding a mdl lock for the trigger name for the duration of the
create/drop.

Patch tested by Elena
parent 5d868486
......@@ -397,6 +397,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
String stmt_query;
bool lock_upgrade_done= FALSE;
MDL_ticket *mdl_ticket= NULL;
MDL_request mdl_request_for_trn;
Query_tables_list backup;
DBUG_ENTER("mysql_create_or_drop_trigger");
......@@ -446,6 +447,16 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
DBUG_RETURN(TRUE);
}
/* Protect against concurrent create/drop */
MDL_REQUEST_INIT(&mdl_request_for_trn, MDL_key::TABLE,
create ? tables->db.str : thd->lex->spname->m_db.str,
thd->lex->spname->m_name.str,
MDL_EXCLUSIVE, MDL_EXPLICIT);
if (thd->mdl_context.acquire_lock(&mdl_request_for_trn,
thd->variables.lock_wait_timeout))
goto end;
if (!create)
{
bool if_exists= thd->lex->if_exists();
......@@ -635,6 +646,9 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
thd->lex->spname->m_name.str, static_cast<uint>(thd->lex->spname->m_name.length));
}
if (mdl_request_for_trn.ticket)
thd->mdl_context.release_lock(mdl_request_for_trn.ticket);
DBUG_RETURN(result);
#ifdef WITH_WSREP
wsrep_error_label:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment