summaryrefslogtreecommitdiff
path: root/sql/sp.cc
diff options
context:
space:
mode:
author <Dao-Gang.Qu@sun.com>2010-04-28 11:26:47 +0800
committer <Dao-Gang.Qu@sun.com>2010-04-28 11:26:47 +0800
commitfa28ba8ba67ff2d2ac2870408e71a78f6e3d5683 (patch)
treeaffacb067fe3e659bd3ef5ed13854c76d8894906 /sql/sp.cc
parenta1b3955f32cfbb5e43191a3f9fb5f4e967965c25 (diff)
downloadmariadb-git-fa28ba8ba67ff2d2ac2870408e71a78f6e3d5683.tar.gz
Bug #51839 mixup of DDL causes slave to stop
Stored routine DDL statements use statement-based replication regardless of the current binlog format. The problem here was that if a DDL statement failed during metadata lock acquisition or opening of mysql.proc, the binlog format would not be reset before returning. So the following DDL or DML statements are binlogged with a wrong binlog format, which causes the slave to stop. The problem can be resolved by grabbing an exclusive MDL lock firstly instead of clearing the current binlog format. So that the binlog format will not be affected when the lock grab returns directly with an error. The same way is taken to open a proc table for update.
Diffstat (limited to 'sql/sp.cc')
-rw-r--r--sql/sp.cc30
1 files changed, 16 insertions, 14 deletions
diff --git a/sql/sp.cc b/sql/sp.cc
index 6aaddb69e05..e7bf15c56d5 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -931,6 +931,11 @@ sp_create_routine(THD *thd, int type, sp_head *sp)
DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE ||
type == TYPE_ENUM_FUNCTION);
+ /* Grab an exclusive MDL lock. */
+ if (lock_routine_name(thd, type == TYPE_ENUM_FUNCTION,
+ sp->m_db.str, sp->m_name.str))
+ DBUG_RETURN(SP_OPEN_TABLE_FAILED);
+
/* Reset sql_mode during data dictionary operations. */
thd->variables.sql_mode= 0;
@@ -942,11 +947,6 @@ sp_create_routine(THD *thd, int type, sp_head *sp)
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
- /* Grab an exclusive MDL lock. */
- if (lock_routine_name(thd, type == TYPE_ENUM_FUNCTION,
- sp->m_db.str, sp->m_name.str))
- DBUG_RETURN(SP_OPEN_TABLE_FAILED);
-
saved_count_cuted_fields= thd->count_cuted_fields;
thd->count_cuted_fields= CHECK_FIELD_WARN;
@@ -1190,6 +1190,14 @@ sp_drop_routine(THD *thd, int type, sp_name *name)
DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE ||
type == TYPE_ENUM_FUNCTION);
+ /* Grab an exclusive MDL lock. */
+ if (lock_routine_name(thd, type == TYPE_ENUM_FUNCTION,
+ name->m_db.str, name->m_name.str))
+ DBUG_RETURN(SP_DELETE_ROW_FAILED);
+
+ if (!(table= open_proc_table_for_update(thd)))
+ DBUG_RETURN(SP_OPEN_TABLE_FAILED);
+
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
@@ -1198,13 +1206,6 @@ sp_drop_routine(THD *thd, int type, sp_name *name)
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
- /* Grab an exclusive MDL lock. */
- if (lock_routine_name(thd, type == TYPE_ENUM_FUNCTION,
- name->m_db.str, name->m_name.str))
- DBUG_RETURN(SP_DELETE_ROW_FAILED);
-
- if (!(table= open_proc_table_for_update(thd)))
- DBUG_RETURN(SP_OPEN_TABLE_FAILED);
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
{
if (table->file->ha_delete_row(table->record[0]))
@@ -1276,6 +1277,9 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
name->m_db.str, name->m_name.str))
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
+ if (!(table= open_proc_table_for_update(thd)))
+ DBUG_RETURN(SP_OPEN_TABLE_FAILED);
+
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
@@ -1284,8 +1288,6 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics)
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
- if (!(table= open_proc_table_for_update(thd)))
- DBUG_RETURN(SP_OPEN_TABLE_FAILED);
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
{
if (type == TYPE_ENUM_FUNCTION && ! trust_function_creators &&