diff options
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 |
commit | fa28ba8ba67ff2d2ac2870408e71a78f6e3d5683 (patch) | |
tree | affacb067fe3e659bd3ef5ed13854c76d8894906 /sql/sp.cc | |
parent | a1b3955f32cfbb5e43191a3f9fb5f4e967965c25 (diff) | |
download | mariadb-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.cc | 30 |
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 && |