mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Approximative fixes for BUG#2610,2611,9100 i.e. WL#2146 binlogging/replication of routines (stored procs and functions).
Approximative, because it's using our binlogging way (what we call "query"-level) and this is not as good as record-level binlog (5.1) would be. It imposes several limitations to routines, and has caveats (which I'll document, and for which the server will try to issue errors but that is not always possible). Reason I don't propagate caller info to the binlog as planned is that on master and slave users may be different; even with that some caveats would remain.
This commit is contained in:
@ -4097,7 +4097,43 @@ unsent_create_error:
|
||||
thd->variables.select_limit= HA_POS_ERROR;
|
||||
|
||||
thd->row_count_func= 0;
|
||||
tmp_disable_binlog(thd); /* don't binlog the substatements */
|
||||
res= sp->execute_procedure(thd, &lex->value_list);
|
||||
reenable_binlog(thd);
|
||||
|
||||
/*
|
||||
We write CALL to binlog; on the opposite we didn't write the
|
||||
substatements. That choice is necessary because the substatements
|
||||
may use local vars.
|
||||
Binlogging should happen when all tables are locked. They are locked
|
||||
just above, and unlocked by close_thread_tables(). All tables which
|
||||
are to be updated are locked like with a table-level write lock, and
|
||||
this also applies to InnoDB (I tested - note that it reduces
|
||||
InnoDB's concurrency as we don't use row-level locks). So binlogging
|
||||
below is safe.
|
||||
Note the limitation: if the SP returned an error, but still did some
|
||||
updates, we do NOT binlog it. This is because otherwise "permission
|
||||
denied", "table does not exist" etc would stop the slave quite
|
||||
often. There is no easy way to know if the SP updated something
|
||||
(even no_trans_update is not suitable, as it may be a transactional
|
||||
autocommit update which happened, and no_trans_update covers only
|
||||
INSERT/UPDATE/LOAD).
|
||||
*/
|
||||
if (mysql_bin_log.is_open() &&
|
||||
(sp->m_chistics->daccess == SP_CONTAINS_SQL ||
|
||||
sp->m_chistics->daccess == SP_MODIFIES_SQL_DATA))
|
||||
{
|
||||
if (res)
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_FAILED_ROUTINE_BREAK_BINLOG,
|
||||
ER(ER_FAILED_ROUTINE_BREAK_BINLOG));
|
||||
else
|
||||
{
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If warnings have been cleared, we have to clear total_warn_count
|
||||
@ -4153,14 +4189,32 @@ unsent_create_error:
|
||||
sp->m_name.str, 0))
|
||||
goto error;
|
||||
memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics));
|
||||
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
|
||||
result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics);
|
||||
else
|
||||
result= sp_update_function(thd, lex->spname, &lex->sp_chistics);
|
||||
if (!trust_routine_creators && mysql_bin_log.is_open() &&
|
||||
!sp->m_chistics->detistic &&
|
||||
(chistics.daccess == SP_CONTAINS_SQL ||
|
||||
chistics.daccess == SP_MODIFIES_SQL_DATA))
|
||||
{
|
||||
my_message(ER_BINLOG_UNSAFE_ROUTINE,
|
||||
ER(ER_BINLOG_UNSAFE_ROUTINE), MYF(0));
|
||||
result= SP_INTERNAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
|
||||
result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics);
|
||||
else
|
||||
result= sp_update_function(thd, lex->spname, &lex->sp_chistics);
|
||||
}
|
||||
}
|
||||
switch (result)
|
||||
{
|
||||
case SP_OK:
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
send_ok(thd);
|
||||
break;
|
||||
case SP_KEY_NOT_FOUND:
|
||||
@ -4237,6 +4291,12 @@ unsent_create_error:
|
||||
switch (result)
|
||||
{
|
||||
case SP_OK:
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
send_ok(thd);
|
||||
break;
|
||||
case SP_KEY_NOT_FOUND:
|
||||
@ -4495,6 +4555,7 @@ unsent_create_error:
|
||||
break;
|
||||
}
|
||||
thd->proc_info="query end";
|
||||
/* Two binlog-related cleanups: */
|
||||
if (thd->one_shot_set)
|
||||
{
|
||||
/*
|
||||
|
Reference in New Issue
Block a user