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
|
#ifdef HAVE_INNOBASE_DB
|
||||||
THD_TRANS *trans;
|
THD_TRANS *trans;
|
||||||
trans = &thd->transaction.all;
|
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,
|
if ((error=innobase_report_binlog_offset_and_commit(thd,
|
||||||
trans->innobase_tid,
|
trans->innobase_tid,
|
||||||
log_file_name,
|
log_file_name,
|
||||||
end_offset)))
|
end_offset)))
|
||||||
{
|
{
|
||||||
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
|
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
|
||||||
error=1;
|
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
|
#endif
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@@ -283,7 +283,7 @@ public:
|
|||||||
create_time(0), check_time(0), update_time(0),
|
create_time(0), check_time(0), update_time(0),
|
||||||
key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
|
key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
|
||||||
ref_length(sizeof(my_off_t)), block_size(0),
|
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); */ }
|
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
|
||||||
int ha_open(const char *name, int mode, int test_if_locked);
|
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);
|
name);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
sql_print_error("After InnoDB crash recovery, trying to truncate "
|
sql_print_error("After InnoDB crash recovery, checking if the binary log "
|
||||||
"the binary log '%s' at position %s corresponding to the "
|
"'%s' contains rolled back transactions which must be "
|
||||||
"last committed transaction...", name, llstr(pos, llbuf1));
|
"removed from it...", name);
|
||||||
/* If we have a too long binlog, cut. If too short, print error */
|
/* 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));
|
int fd= my_open(name, O_EXCL | O_APPEND | O_BINARY | O_WRONLY, MYF(MY_WME));
|
||||||
if (fd < 0)
|
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))))
|
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 "
|
sql_print_error("The binary log '%s' is shorter than its expected size "
|
||||||
"(actual: %s, expected: %s) so it misses at least one "
|
"(actual: %s, expected: %s) so it misses at least one "
|
||||||
"committed transaction; so it should not be used for "
|
"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));
|
llstr(pos, llbuf2));
|
||||||
error= 1;
|
error= 1;
|
||||||
goto err;
|
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 com_stat[(uint) SQLCOM_END], com_other, back_log;
|
||||||
extern ulong specialflag, current_pid;
|
extern ulong specialflag, current_pid;
|
||||||
extern ulong expire_logs_days, sync_binlog_period, sync_binlog_counter;
|
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 test_flags,select_errors,ha_open_options;
|
||||||
extern uint protocol_version, mysqld_port, dropping_tables;
|
extern uint protocol_version, mysqld_port, dropping_tables;
|
||||||
extern uint delay_key_write_options, lower_case_table_names;
|
extern uint delay_key_write_options, lower_case_table_names;
|
||||||
|
@@ -2538,6 +2538,12 @@ server.");
|
|||||||
|
|
||||||
if (opt_innodb_safe_binlog)
|
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)
|
if (innobase_flush_log_at_trx_commit != 1)
|
||||||
{
|
{
|
||||||
sql_print_error("Warning: --innodb-safe-binlog is meaningful only if "
|
sql_print_error("Warning: --innodb-safe-binlog is meaningful only if "
|
||||||
@@ -4641,9 +4647,8 @@ replicating a LOAD DATA INFILE command.",
|
|||||||
effect).
|
effect).
|
||||||
*/
|
*/
|
||||||
{"innodb_safe_binlog", OPT_INNODB_SAFE_BINLOG,
|
{"innodb_safe_binlog", OPT_INNODB_SAFE_BINLOG,
|
||||||
"After a crash recovery by InnoDB, truncate the binary log to the last \
|
"After a crash recovery by InnoDB, truncate the binary log after the last "
|
||||||
InnoDB committed transaction. Use only if this server updates ONLY InnoDB \
|
"not-rolled-back statement/transaction.",
|
||||||
tables.",
|
|
||||||
(gptr*) &opt_innodb_safe_binlog, (gptr*) &opt_innodb_safe_binlog,
|
(gptr*) &opt_innodb_safe_binlog, (gptr*) &opt_innodb_safe_binlog,
|
||||||
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
|
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user