mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Bug #40116: Uncommited changes are replicated and stay on slave
after rollback on master When starting a transaction with a statement containing changes to both transactional tables and non-transactional tables, the statement is considered as non-transactional and is therefore written directly to the binary log. This behaviour was present in 5.0, and has propagated to 5.1. If a trigger containing a change of a non-transactional table is added to a transactional table, any changes to the transactional table is "tainted" as non-transactional. This patch solves the problem by removing the existing "hack" that allows non-transactional statements appearing first in a transaction to be written directly to the binary log. Instead, anything inside a transaction is treaded as part of the transaction and not written to the binary log until the transaction is committed.
This commit is contained in:
61
sql/log.cc
61
sql/log.cc
@ -1478,60 +1478,11 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
|
||||
}
|
||||
|
||||
/*
|
||||
Decision table for committing a transaction. The top part, the
|
||||
*conditions* represent different cases that can occur, and hte
|
||||
bottom part, the *actions*, represent what should be done in that
|
||||
particular case.
|
||||
We commit the transaction if:
|
||||
|
||||
Real transaction 'all' was true
|
||||
- We are not in a transaction and committing a statement, or
|
||||
|
||||
Statement in cache There were at least one statement in the
|
||||
transaction cache
|
||||
|
||||
In transaction We are inside a transaction
|
||||
|
||||
Stmt modified non-trans The statement being committed modified a
|
||||
non-transactional table
|
||||
|
||||
All modified non-trans Some statement before this one in the
|
||||
transaction modified a non-transactional
|
||||
table
|
||||
|
||||
|
||||
============================= = = = = = = = = = = = = = = = =
|
||||
Real transaction N N N N N N N N N N N N N N N N
|
||||
Statement in cache N N N N N N N N Y Y Y Y Y Y Y Y
|
||||
In transaction N N N N Y Y Y Y N N N N Y Y Y Y
|
||||
Stmt modified non-trans N N Y Y N N Y Y N N Y Y N N Y Y
|
||||
All modified non-trans N Y N Y N Y N Y N Y N Y N Y N Y
|
||||
|
||||
Action: (C)ommit/(A)ccumulate C C - C A C - C - - - - A A - A
|
||||
============================= = = = = = = = = = = = = = = = =
|
||||
|
||||
|
||||
============================= = = = = = = = = = = = = = = = =
|
||||
Real transaction Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
|
||||
Statement in cache N N N N N N N N Y Y Y Y Y Y Y Y
|
||||
In transaction N N N N Y Y Y Y N N N N Y Y Y Y
|
||||
Stmt modified non-trans N N Y Y N N Y Y N N Y Y N N Y Y
|
||||
All modified non-trans N Y N Y N Y N Y N Y N Y N Y N Y
|
||||
|
||||
(C)ommit/(A)ccumulate/(-) - - - - C C - C - - - - C C - C
|
||||
============================= = = = = = = = = = = = = = = = =
|
||||
|
||||
In other words, we commit the transaction if and only if both of
|
||||
the following are true:
|
||||
- We are not in a transaction and committing a statement
|
||||
|
||||
- We are in a transaction and one (or more) of the following are
|
||||
true:
|
||||
|
||||
- A full transaction is committed
|
||||
|
||||
OR
|
||||
|
||||
- A non-transactional statement is committed and there is
|
||||
no statement cached
|
||||
- We are in a transaction and a full transaction is committed
|
||||
|
||||
Otherwise, we accumulate the statement
|
||||
*/
|
||||
@ -1544,11 +1495,7 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all)
|
||||
YESNO(in_transaction),
|
||||
YESNO(thd->transaction.all.modified_non_trans_table),
|
||||
YESNO(thd->transaction.stmt.modified_non_trans_table)));
|
||||
if (in_transaction &&
|
||||
(all ||
|
||||
(!trx_data->at_least_one_stmt &&
|
||||
thd->transaction.stmt.modified_non_trans_table)) ||
|
||||
!in_transaction && !all)
|
||||
if (!in_transaction || all)
|
||||
{
|
||||
Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
|
||||
qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
|
||||
|
Reference in New Issue
Block a user