diff options
author | mats@romeo.(none) <> | 2007-04-12 08:58:04 +0200 |
---|---|---|
committer | mats@romeo.(none) <> | 2007-04-12 08:58:04 +0200 |
commit | 11fc24ef24469acfd8ef95f5df1c691bfbed6074 (patch) | |
tree | 751a12cfad714ca627a74b77e5a1ed3ef9a68b5e /sql/rpl_rli.cc | |
parent | 220c45319423ca234d3eaa3e1028a097cd2f4548 (diff) | |
download | mariadb-git-11fc24ef24469acfd8ef95f5df1c691bfbed6074.tar.gz |
BUG#25688 (RBR: circular replication may cause STMT_END_F flags to be
skipped):
By moving statement end actions from Rows_log_event::do_apply_event() to
Rows_log_event::do_update_pos() they will always be executed, even if
Rows_log_event::do_apply_event() is skipped because the event originated
at the same server. This because Rows_log_event::do_update_pos() is always
executed (unless Rows_log_event::do_apply_event() failed with an error,
in which case the slave stops with an error anyway).
Adding test case.
Fixing logic to detect if inside a group. If a rotate event occured
when an initial prefix of events for a statement, but for which the
table did contain a key, last_event_start_time is set to zero, causing
rotate to end the group but without unlocking any tables. This left a
lock hanging around, which subsequently triggered an assertion when a
second attempt was made to lock the same sequence of tables.
In order to solve the above problem, a new flag was added to the relay
log info structure that is used to indicate that the replication thread
is currently executing a statement. Using this flag, the replication
thread is in a group if it is either in a statement or inside a trans-
action.
The patch also eliminates some gratuitous header file inclusions that
were not needed (and caused compile errors) and replaced them with
forward definitions.
Diffstat (limited to 'sql/rpl_rli.cc')
-rw-r--r-- | sql/rpl_rli.cc | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index b0db355154e..72e307d828b 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -15,6 +15,7 @@ #include "mysql_priv.h" +#include "rpl_mi.h" #include "rpl_rli.h" #include <my_dir.h> // For MY_STAT #include "sql_repl.h" // For check_binlog_magic @@ -37,7 +38,7 @@ st_relay_log_info::st_relay_log_info() inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE), until_log_pos(0), retried_trans(0), tables_to_lock(0), tables_to_lock_count(0), - last_event_start_time(0) + last_event_start_time(0), m_flags(0) { DBUG_ENTER("st_relay_log_info::st_relay_log_info"); @@ -1086,6 +1087,52 @@ bool st_relay_log_info::cached_charset_compare(char *charset) const } +void st_relay_log_info::stmt_done(my_off_t const event_master_log_pos, + time_t event_creation_time) +{ + clear_flag(IN_STMT); + + /* + If in a transaction, and if the slave supports transactions, just + inc_event_relay_log_pos(). We only have to check for OPTION_BEGIN + (not OPTION_NOT_AUTOCOMMIT) as transactions are logged with + BEGIN/COMMIT, not with SET AUTOCOMMIT= . + + CAUTION: opt_using_transactions means innodb || bdb ; suppose the + master supports InnoDB and BDB, but the slave supports only BDB, + problems will arise: - suppose an InnoDB table is created on the + master, - then it will be MyISAM on the slave - but as + opt_using_transactions is true, the slave will believe he is + transactional with the MyISAM table. And problems will come when + one does START SLAVE; STOP SLAVE; START SLAVE; (the slave will + resume at BEGIN whereas there has not been any rollback). This is + the problem of using opt_using_transactions instead of a finer + "does the slave support _transactional handler used on the + master_". + + More generally, we'll have problems when a query mixes a + transactional handler and MyISAM and STOP SLAVE is issued in the + middle of the "transaction". START SLAVE will resume at BEGIN + while the MyISAM table has already been updated. + */ + if ((sql_thd->options & OPTION_BEGIN) && opt_using_transactions) + inc_event_relay_log_pos(); + else + { + inc_group_relay_log_pos(event_master_log_pos); + flush_relay_log_info(this); + /* + Note that Rotate_log_event::do_apply_event() does not call this + function, so there is no chance that a fake rotate event resets + last_master_timestamp. Note that we update without mutex + (probably ok - except in some very rare cases, only consequence + is that value may take some time to display in + Seconds_Behind_Master - not critical). + */ + last_master_timestamp= event_creation_time; + } +} + #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) void st_relay_log_info::cleanup_context(THD *thd, bool error) { @@ -1112,6 +1159,7 @@ void st_relay_log_info::cleanup_context(THD *thd, bool error) m_table_map.clear_tables(); close_thread_tables(thd); clear_tables_to_lock(); + clear_flag(IN_STMT); last_event_start_time= 0; DBUG_VOID_RETURN; } |