Alfranio Correia wrote:
> #At
> file:///home/acorreia/workspace.sun/repository.mysql/bzrwork/bug-28976/mysql-5.1-bugteam/
> based on revid:joro@stripped
>
> 3018 Alfranio Correia 2009-07-10
> BUG#28976 Mixing trans and non-trans tables in one transaction results in
> incorrect
> binlog
>
> Mixing transactional (T) and non-transactional (N) tables on behalf of a
> transaction may lead to inconsistencies among masters and slaves. The problem
> stems from the fact that although modifications done to non-transactional
> tables
> on behalf of a transaction become immediately visible to the other connections
> it
> does not immediately gets to the binary log and therefore consistency is
> broken.
>
> After the WL#2687, it will be safe to use either the MIXED or ROW mode to do
> such
> mix. Changes to non-transactional tables will immediately get to the binary
> log
> as rows. Under the STATEMENT mode, however, changing non-transactional tables
> before transactional ones is the only possible safe mix. This happen because
> it
> is as if such changes had not been executed on the behalf of a transaction.
> On the other hand, other combinations may hide a causal dependency, thus
> making
> impossible to immediately write statements with non-transactional tables to
> the
> binary log before committing or rolling back the transaction.
>
> In this bug, with fix two issues regarding the mix of T statements and N
> statements on behalf of a transaction when in STATEMENT mode.
>
> First, multi-level (e.g. a statement that fires a trigger) or multi-table
> table
> statements (e.g. update t1, t2...) were not handled correctly. In such cases,
> only the flag "modified_non_trans_table" is not enough to reflect that both a
> N
> and T tables were changed. To circumvent this issue, we also check if an
> engine
> is registered in the handler's list and changed something meaning that a M
> table
> was modified.
>
> Second, the fix for BUG#43929 introduced a regression issue. In a nutshell,
> when a N statement fails on behalf of a transaction, it is written to the
> binary
> log with the error code appended. Unfortunately, after BUG#43929, this
> scenario
> was flushing the transactional cache (i.e. the cache where changes a stored
> while
typo: changes a stored => changes are stored
> processing a transaction before being written to the binary log upon a commit
> or rollback) although a commit or a rollback was not issued. To fix this
> issue,
> we avoid flushing the transactional cache when a commit or rollback is not
> issued.
[snip]
> /*
> Save position of binary log transaction cache.
> @@ -1578,8 +1590,11 @@ static int binlog_rollback(handlerton *h
> transactional table in that statement as well, which needs to be
> rolled back on the slave.
> */
> - Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, TRUE, 0);
> - error= binlog_end_trans(thd, trx_data, &qev, all);
> + if (all || !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT)))
Please combine this with the condition before this. And I think the
ROLLBACK should be flushed if OPTION_KEEP_LOG too.
> + {
> + Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, TRUE, 0);
> + error= binlog_end_trans(thd, trx_data, &qev, all);
> + }
> }
> else
> {
> @@ -4044,7 +4059,8 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
> (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
> IO_CACHE *trans_log= &trx_data->trans_log;
> my_off_t trans_log_pos= my_b_tell(trans_log);
> - if (event_info->get_cache_stmt() || trans_log_pos != 0)
> + if (event_info->get_cache_stmt() || trans_log_pos != 0 ||
> + stmt_has_updated_trans_table(thd))
> {
> DBUG_PRINT("info", ("Using trans_log: cache: %d, trans_log_pos: %lu",
> event_info->get_cache_stmt(),
>