mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
BUG#46364 MyISAM transbuffer problems (NTM problem)
It is well-known that due to concurrency issues, a slave can become inconsistent when a transaction contains updates to both transaction and non-transactional tables in statement and mixed modes. In a nutshell, the current code-base tries to preserve causality among the statements by writing non-transactional statements to the txn-cache which is flushed upon commit. However, modifications done to non-transactional tables on behalf of a transaction become immediately visible to other connections but may not immediately get into the binary log and therefore consistency may be broken. In general, it is impossible to automatically detect causality/dependency among statements by just analyzing the statements sent to the server. This happen because dependency may be hidden in the application code and it is necessary to know a priori all the statements processed in the context of a transaction such as in a procedure. Moreover, even for the few cases that we could automatically address in the server, the computation effort required could make the approach infeasible. So, in this patch we introduce the option - "--binlog-direct-non-transactional-updates" that can be used to bypass the current behavior in order to write directly to binary log statements that change non-transactional tables.
This commit is contained in:
23
sql/log.cc
23
sql/log.cc
@ -4284,12 +4284,20 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
|
||||
#if defined(USING_TRANSACTIONS)
|
||||
/*
|
||||
Should we write to the binlog cache or to the binlog on disk?
|
||||
|
||||
Write to the binlog cache if:
|
||||
- it is already not empty (meaning we're in a transaction; note that the
|
||||
present event could be about a non-transactional table, but still we need
|
||||
to write to the binlog cache in that case to handle updates to mixed
|
||||
trans/non-trans table types the best possible in binlogging)
|
||||
- or if the event asks for it (cache_stmt == TRUE).
|
||||
1 - a transactional engine/table is updated (stmt_has_updated_trans_table == TRUE);
|
||||
2 - or the event asks for it (cache_stmt == TRUE);
|
||||
3 - or the cache is already not empty (meaning we're in a transaction;
|
||||
note that the present event could be about a non-transactional table, but
|
||||
still we need to write to the binlog cache in that case to handle updates
|
||||
to mixed trans/non-trans table types).
|
||||
|
||||
Write to the binlog on disk if only a non-transactional engine is
|
||||
updated and:
|
||||
1 - the binlog cache is empty or;
|
||||
2 - --binlog-direct-non-transactional-updates is set and we are about to
|
||||
use the statement format. When using the row format (cache_stmt == TRUE).
|
||||
*/
|
||||
if (opt_using_transactions && thd)
|
||||
{
|
||||
@ -4300,8 +4308,9 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
|
||||
(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 ||
|
||||
stmt_has_updated_trans_table(thd))
|
||||
if (event_info->get_cache_stmt() || stmt_has_updated_trans_table(thd) ||
|
||||
(!thd->variables.binlog_direct_non_trans_update &&
|
||||
trans_log_pos != 0))
|
||||
{
|
||||
DBUG_PRINT("info", ("Using trans_log: cache: %d, trans_log_pos: %lu",
|
||||
event_info->get_cache_stmt(),
|
||||
|
Reference in New Issue
Block a user