mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Final part of WL#1717 "innodb/binlog consistency". This is to resolve
a limitation of yesterday's implementation: if there was an unfinished transaction (COMMIT not typed), and some MyISAM tables were then updated, and then mysqld crashes, then at restart the server would use the too old binlog offset known by InnoDB to cut the binlog, thus cutting the successful MyISAM updates. We fix this by reporting the binlog offset into InnoDB even if InnoDB was not affected at all by the update. But the feature is still disabled until we decide if it can go into 4.1.3. sql/handler.cc: How we report the binlog offset into InnoDB: - if the update affected InnoDB, it will happen naturally - otherwise (for example MyISAM update not in an InnoDB transaction), we explicitely report it. sql/handler.h: removing warning (noticed this) sql/log.cc: clearer messages when truncating binlog. sql/mysql_priv.h: need to see opt_innodb_safe_binlog in handler.cc sql/mysqld.cc: No innodb-safe-binlog if no InnoDB. Updating message as now we work with MyISAM.
This commit is contained in:
@@ -385,17 +385,25 @@ int ha_report_binlog_offset_and_commit(THD *thd,
|
||||
#ifdef HAVE_INNOBASE_DB
|
||||
THD_TRANS *trans;
|
||||
trans = &thd->transaction.all;
|
||||
if (trans->innobase_tid)
|
||||
if (trans->innobase_tid && trans->innodb_active_trans)
|
||||
{
|
||||
/*
|
||||
If we updated some InnoDB tables (innodb_active_trans is true), the
|
||||
binlog coords will be reported into InnoDB during the InnoDB commit
|
||||
(innobase_report_binlog_offset_and_commit). But if we updated only
|
||||
non-InnoDB tables, we need an explicit call to report it.
|
||||
*/
|
||||
if ((error=innobase_report_binlog_offset_and_commit(thd,
|
||||
trans->innobase_tid,
|
||||
log_file_name,
|
||||
end_offset)))
|
||||
trans->innobase_tid,
|
||||
log_file_name,
|
||||
end_offset)))
|
||||
{
|
||||
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
|
||||
error=1;
|
||||
}
|
||||
}
|
||||
else if (opt_innodb_safe_binlog) // Don't report if not useful
|
||||
innobase_store_binlog_offset_and_flush_log(log_file_name, end_offset);
|
||||
#endif
|
||||
return error;
|
||||
}
|
||||
|
@@ -283,7 +283,7 @@ public:
|
||||
create_time(0), check_time(0), update_time(0),
|
||||
key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
|
||||
ref_length(sizeof(my_off_t)), block_size(0),
|
||||
raid_type(0), ft_handler(0), implicit_emptied(0), inited(NONE)
|
||||
raid_type(0), ft_handler(0), inited(NONE), implicit_emptied(0)
|
||||
{}
|
||||
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
|
||||
int ha_open(const char *name, int mode, int test_if_locked);
|
||||
|
15
sql/log.cc
15
sql/log.cc
@@ -2073,9 +2073,9 @@ bool MYSQL_LOG::cut_spurious_tail()
|
||||
name);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
sql_print_error("After InnoDB crash recovery, trying to truncate "
|
||||
"the binary log '%s' at position %s corresponding to the "
|
||||
"last committed transaction...", name, llstr(pos, llbuf1));
|
||||
sql_print_error("After InnoDB crash recovery, checking if the binary log "
|
||||
"'%s' contains rolled back transactions which must be "
|
||||
"removed from it...", name);
|
||||
/* If we have a too long binlog, cut. If too short, print error */
|
||||
int fd= my_open(name, O_EXCL | O_APPEND | O_BINARY | O_WRONLY, MYF(MY_WME));
|
||||
if (fd < 0)
|
||||
@@ -2091,10 +2091,17 @@ bool MYSQL_LOG::cut_spurious_tail()
|
||||
|
||||
if (pos > (actual_size= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME))))
|
||||
{
|
||||
/*
|
||||
Note that when we have MyISAM rollback this error message should be
|
||||
reconsidered.
|
||||
*/
|
||||
sql_print_error("The binary log '%s' is shorter than its expected size "
|
||||
"(actual: %s, expected: %s) so it misses at least one "
|
||||
"committed transaction; so it should not be used for "
|
||||
"replication.", name, llstr(actual_size, llbuf1),
|
||||
"replication or point-in-time recovery. You would need "
|
||||
"to restart slaves from a fresh master's data "
|
||||
"snapshot ",
|
||||
name, llstr(actual_size, llbuf1),
|
||||
llstr(pos, llbuf2));
|
||||
error= 1;
|
||||
goto err;
|
||||
|
@@ -869,7 +869,7 @@ extern ulong rpl_recovery_rank, thread_cache_size;
|
||||
extern ulong com_stat[(uint) SQLCOM_END], com_other, back_log;
|
||||
extern ulong specialflag, current_pid;
|
||||
extern ulong expire_logs_days, sync_binlog_period, sync_binlog_counter;
|
||||
extern my_bool relay_log_purge;
|
||||
extern my_bool relay_log_purge, opt_innodb_safe_binlog;
|
||||
extern uint test_flags,select_errors,ha_open_options;
|
||||
extern uint protocol_version, mysqld_port, dropping_tables;
|
||||
extern uint delay_key_write_options, lower_case_table_names;
|
||||
|
@@ -2538,6 +2538,12 @@ server.");
|
||||
|
||||
if (opt_innodb_safe_binlog)
|
||||
{
|
||||
if (have_innodb != SHOW_OPTION_YES)
|
||||
{
|
||||
sql_print_error("Error: --innodb-safe-binlog is meaningful only if "
|
||||
"the InnoDB storage engine is enabled in the server.");
|
||||
unireg_abort(1);
|
||||
}
|
||||
if (innobase_flush_log_at_trx_commit != 1)
|
||||
{
|
||||
sql_print_error("Warning: --innodb-safe-binlog is meaningful only if "
|
||||
@@ -4641,9 +4647,8 @@ replicating a LOAD DATA INFILE command.",
|
||||
effect).
|
||||
*/
|
||||
{"innodb_safe_binlog", OPT_INNODB_SAFE_BINLOG,
|
||||
"After a crash recovery by InnoDB, truncate the binary log to the last \
|
||||
InnoDB committed transaction. Use only if this server updates ONLY InnoDB \
|
||||
tables.",
|
||||
"After a crash recovery by InnoDB, truncate the binary log after the last "
|
||||
"not-rolled-back statement/transaction.",
|
||||
(gptr*) &opt_innodb_safe_binlog, (gptr*) &opt_innodb_safe_binlog,
|
||||
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user