mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Bug #55498 SHOW CREATE TRIGGER takes wrong type of metadata lock
The first problem was that SHOW CREATE TRIGGER took a stronger metadata lock than required. This caused the statement to be blocked when it was not needed. For example, LOCK TABLE WRITE in one connection would block SHOW CREATE TRIGGER in another connection. Another problem was that a SHOW CREATE TRIGGER statement issued inside a transaction did not release its metadata locks at the end of the statement execution. This happened even if SHOW CREATE TRIGGER is an information statement. The consequence was that SHOW CREATE TRIGGER was able to block other connections from accessing the table (e.g. using ALTER TABLE). This patch fixes the problem by changing SHOW CREATE TRIGGER to take a MDL_SHARED_HIGH_PRIO metadata lock similar to what is already done for SHOW CREATE TABLE. The patch also changes SHOW CREATE TRIGGER to explicitly release any metadata locks taken by the statement after it completes. Test case added to show_check.test.
This commit is contained in:
@@ -7779,6 +7779,10 @@ TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name)
|
||||
bool show_create_trigger(THD *thd, const sp_name *trg_name)
|
||||
{
|
||||
TABLE_LIST *lst= get_trigger_table(thd, trg_name);
|
||||
uint num_tables; /* NOTE: unused, only to pass to open_tables(). */
|
||||
Table_triggers_list *triggers;
|
||||
int trigger_idx;
|
||||
bool error= TRUE;
|
||||
|
||||
if (!lst)
|
||||
return TRUE;
|
||||
@@ -7790,35 +7794,35 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name)
|
||||
}
|
||||
|
||||
/*
|
||||
Open the table by name in order to load Table_triggers_list object.
|
||||
|
||||
NOTE: there is race condition here -- the table can be dropped after
|
||||
LOCK_open is released. It will be fixed later by acquiring shared
|
||||
metadata lock on trigger or table name.
|
||||
Metadata locks taken during SHOW CREATE TRIGGER should be released when
|
||||
the statement completes as it is an information statement.
|
||||
*/
|
||||
MDL_ticket *mdl_savepoint= thd->mdl_context.mdl_savepoint();
|
||||
|
||||
uint num_tables; /* NOTE: unused, only to pass to open_tables(). */
|
||||
|
||||
if (open_tables(thd, &lst, &num_tables, 0))
|
||||
/*
|
||||
Open the table by name in order to load Table_triggers_list object.
|
||||
*/
|
||||
if (open_tables(thd, &lst, &num_tables,
|
||||
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL))
|
||||
{
|
||||
my_error(ER_TRG_CANT_OPEN_TABLE, MYF(0),
|
||||
(const char *) trg_name->m_db.str,
|
||||
(const char *) lst->table_name);
|
||||
|
||||
return TRUE;
|
||||
goto exit;
|
||||
|
||||
/* Perform closing actions and return error status. */
|
||||
}
|
||||
|
||||
Table_triggers_list *triggers= lst->table->triggers;
|
||||
triggers= lst->table->triggers;
|
||||
|
||||
if (!triggers)
|
||||
{
|
||||
my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
|
||||
return TRUE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
int trigger_idx= triggers->find_trigger_by_name(&trg_name->m_name);
|
||||
trigger_idx= triggers->find_trigger_by_name(&trg_name->m_name);
|
||||
|
||||
if (trigger_idx < 0)
|
||||
{
|
||||
@@ -7826,16 +7830,22 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name)
|
||||
(const char *) trg_name->m_db.str,
|
||||
(const char *) lst->table_name);
|
||||
|
||||
return TRUE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
return show_create_trigger_impl(thd, triggers, trigger_idx);
|
||||
error= show_create_trigger_impl(thd, triggers, trigger_idx);
|
||||
|
||||
/*
|
||||
NOTE: if show_create_trigger_impl() failed, that means we could not
|
||||
send data to the client. In this case we simply raise the error
|
||||
status and client connection will be closed.
|
||||
*/
|
||||
|
||||
exit:
|
||||
close_thread_tables(thd);
|
||||
/* Release any metadata locks taken during SHOW CREATE TRIGGER. */
|
||||
thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
|
||||
return error;
|
||||
}
|
||||
|
||||
class IS_internal_schema_access : public ACL_internal_schema_access
|
||||
|
||||
Reference in New Issue
Block a user