Commit 8c774b12 authored by Nikita Malyavin's avatar Nikita Malyavin

MDEV-31646 preserve DMLs in case of online binlog fault

A 32-bit server build has a limitation of 2^32 bytes max for IO_CACHE.
This is quite a reachable value for a single transaction.

If DML reaches it, and the engine is not rollback-capable, then the last
record operation will be lost after ALTER TABLE.

To avoid it, report the error to the ALTER TABLE side and ignore it on the
DML side. Thus, a DML will not fail because of an online alter log failure.
parent ca64ddcc
...@@ -1367,7 +1367,7 @@ NOT FOUND /Slave SQL/ in mysqld.1.err ...@@ -1367,7 +1367,7 @@ NOT FOUND /Slave SQL/ in mysqld.1.err
# MDEV-31646 Online alter applies binlog cache limit to cache writes # MDEV-31646 Online alter applies binlog cache limit to cache writes
# #
create table t (pk int primary key, a varchar(100)) engine=MyISAM; create table t (pk int primary key, a varchar(100)) engine=MyISAM;
insert into t select seq, repeat('x', 100) from seq_1_to_500; insert into t select seq, repeat('x', 100) from seq_1_to_50;
set @cache.size= @@max_binlog_cache_size; set @cache.size= @@max_binlog_cache_size;
set global max_binlog_cache_size= 4096; set global max_binlog_cache_size= 4096;
set debug_sync= 'now wait_for do_updates'; set debug_sync= 'now wait_for do_updates';
...@@ -1385,29 +1385,56 @@ Level Code Message ...@@ -1385,29 +1385,56 @@ Level Code Message
connection default; connection default;
drop table t; drop table t;
set debug_sync= reset; set debug_sync= reset;
set global max_binlog_cache_size= @cache.size;
# Now make sure that smaller limits will be processed fine # Now make sure that smaller limits will be processed fine
set @old_dbug=@@debug_dbug; set debug_dbug="+d,online_alter_small_cache_2";
set debug_dbug="+d,online_alter_small_cache";
create table t (pk int primary key, a varchar(100)) engine=MyISAM; create table t (pk int primary key, a varchar(100)) engine=MyISAM;
insert into t select seq, repeat('x', 100) from seq_1_to_500; insert into t select seq, repeat('x', 100) from seq_1_to_50;
set @cache.size= @@max_binlog_cache_size;
set global max_binlog_cache_size= 4096;
connection con1; connection con1;
set debug_sync= 'alter_table_online_progress signal do_updates wait_for go'; set debug_dbug="+d,online_alter_small_cache_2";
set debug_sync= 'alter_table_online_before_lock signal do_updates wait_for go';
alter table t add b int, algorithm=copy, lock=none; alter table t add b int, algorithm=copy, lock=none;
connection default; connection default;
set debug_sync= 'now wait_for do_updates'; set debug_sync= 'now wait_for do_updates';
update t set a = repeat('y', 100); update t set a = repeat('y', 100);
ERROR HY000: Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mariadbd variable and try again Warnings:
Warning 1026 Error writing file 'online-alter-binlog' (errno: 27 "File too large")
show warnings; show warnings;
Level Code Message Level Code Message
Error 1197 Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mariadbd variable and try again Warning 1026 Error writing file 'online-alter-binlog' (errno: 27 "File too large")
Error 1534 Writing one row to the row-based binary log failed
Warning 1196 Some non-transactional changed tables couldn't be rolled back
set debug_sync= 'now signal go'; set debug_sync= 'now signal go';
connection con1; connection con1;
ERROR HY000: IO Write error: (27, File too large)
show warnings; show warnings;
Level Code Message Level Code Message
Error 1811 IO Write error: (27, File too large)
set debug_dbug= @old_dbug;
connection default;
drop table t;
set debug_sync= reset;
set debug_dbug= @old_dbug;
set debug_dbug="+d,online_alter_small_cache_1";
create table t (pk int primary key, a varchar(100)) engine=MyISAM;
insert into t select seq, repeat('x', 100) from seq_1_to_50;
connection con1;
set debug_dbug="+d,online_alter_small_cache_1";
set debug_sync= 'alter_table_online_before_lock signal do_updates wait_for go';
alter table t add b int, algorithm=copy, lock=none;
connection default;
set debug_sync= 'now wait_for do_updates';
update t set a = repeat('y', 100);
Warnings:
Warning 1026 Error writing file 'online-alter-binlog' (errno: 27 "File too large")
show warnings;
Level Code Message
Warning 1026 Error writing file 'online-alter-binlog' (errno: 27 "File too large")
set debug_sync= 'now signal go';
connection con1;
ERROR HY000: IO Write error: (27, File too large)
show warnings;
Level Code Message
Error 1811 IO Write error: (27, File too large)
set debug_dbug= @old_dbug;
connection default; connection default;
drop table t; drop table t;
set debug_sync= reset; set debug_sync= reset;
......
...@@ -1561,7 +1561,7 @@ let SEARCH_PATTERN= Slave SQL; ...@@ -1561,7 +1561,7 @@ let SEARCH_PATTERN= Slave SQL;
--echo # MDEV-31646 Online alter applies binlog cache limit to cache writes --echo # MDEV-31646 Online alter applies binlog cache limit to cache writes
--echo # --echo #
create table t (pk int primary key, a varchar(100)) engine=MyISAM; create table t (pk int primary key, a varchar(100)) engine=MyISAM;
insert into t select seq, repeat('x', 100) from seq_1_to_500; insert into t select seq, repeat('x', 100) from seq_1_to_50;
set @cache.size= @@max_binlog_cache_size; set @cache.size= @@max_binlog_cache_size;
set global max_binlog_cache_size= 4096; set global max_binlog_cache_size= 4096;
...@@ -1586,38 +1586,39 @@ show warnings; ...@@ -1586,38 +1586,39 @@ show warnings;
--connection default --connection default
drop table t; drop table t;
set debug_sync= reset; set debug_sync= reset;
set global max_binlog_cache_size= @cache.size;
--echo # Now make sure that smaller limits will be processed fine --echo # Now make sure that smaller limits will be processed fine
let $i=2;
set @old_dbug=@@debug_dbug; while ($i) {
set debug_dbug="+d,online_alter_small_cache"; eval set debug_dbug="+d,online_alter_small_cache_$i";
create table t (pk int primary key, a varchar(100)) engine=MyISAM; create table t (pk int primary key, a varchar(100)) engine=MyISAM;
insert into t select seq, repeat('x', 100) from seq_1_to_500; insert into t select seq, repeat('x', 100) from seq_1_to_50;
set @cache.size= @@max_binlog_cache_size; --connection con1
set global max_binlog_cache_size= 4096; eval set debug_dbug="+d,online_alter_small_cache_$i";
set debug_sync= 'alter_table_online_before_lock signal do_updates wait_for go';
--connection con1 send alter table t add b int, algorithm=copy, lock=none;
set debug_sync= 'alter_table_online_progress signal do_updates wait_for go';
--send --connection default
alter table t add b int, algorithm=copy, lock=none; set debug_sync= 'now wait_for do_updates';
update t set a = repeat('y', 100);
--connection default show warnings;
set debug_sync= 'now wait_for do_updates';
--error ER_TRANS_CACHE_FULL set debug_sync= 'now signal go';
update t set a = repeat('y', 100);
show warnings; --connection con1
--error ER_IO_WRITE_ERROR
set debug_sync= 'now signal go'; --reap
show warnings;
--connection con1
--reap set debug_dbug= @old_dbug;
show warnings; --connection default
drop table t;
--connection default set debug_sync= reset;
drop table t; set debug_dbug= @old_dbug;
set debug_sync= reset; dec $i;
set debug_dbug= @old_dbug; }
--disconnect con1 --disconnect con1
--disconnect con2 --disconnect con2
......
...@@ -2273,7 +2273,7 @@ int binlog_log_row_online_alter(TABLE* table, const uchar *before_record, ...@@ -2273,7 +2273,7 @@ int binlog_log_row_online_alter(TABLE* table, const uchar *before_record,
{ {
THD *thd= table->in_use; THD *thd= table->in_use;
if (!table->online_alter_cache) if (unlikely(!table->online_alter_cache))
{ {
table->online_alter_cache= online_alter_binlog_get_cache_data(thd, table); table->online_alter_cache= online_alter_binlog_get_cache_data(thd, table);
trans_register_ha(thd, false, binlog_hton, 0); trans_register_ha(thd, false, binlog_hton, 0);
...@@ -2284,6 +2284,9 @@ int binlog_log_row_online_alter(TABLE* table, const uchar *before_record, ...@@ -2284,6 +2284,9 @@ int binlog_log_row_online_alter(TABLE* table, const uchar *before_record,
// We need to log all columns for the case if alter table changes primary key // We need to log all columns for the case if alter table changes primary key
DBUG_ASSERT(!before_record || bitmap_is_set_all(table->read_set)); DBUG_ASSERT(!before_record || bitmap_is_set_all(table->read_set));
MY_BITMAP *old_rpl_write_set= table->rpl_write_set; MY_BITMAP *old_rpl_write_set= table->rpl_write_set;
Dummy_error_handler dummy_handler;
thd->push_internal_handler(&dummy_handler);
table->rpl_write_set= &table->s->all_set; table->rpl_write_set= &table->s->all_set;
int error= (*log_func)(thd, table, table->s->online_alter_binlog, int error= (*log_func)(thd, table, table->s->online_alter_binlog,
...@@ -2291,8 +2294,14 @@ int binlog_log_row_online_alter(TABLE* table, const uchar *before_record, ...@@ -2291,8 +2294,14 @@ int binlog_log_row_online_alter(TABLE* table, const uchar *before_record,
before_record, after_record); before_record, after_record);
table->rpl_write_set= old_rpl_write_set; table->rpl_write_set= old_rpl_write_set;
thd->pop_internal_handler();
return unlikely(error) ? HA_ERR_RBR_LOGGING_FAILED : 0; if (unlikely(error))
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_DISK_FULL,
"Broken online alter log. "
"ALTER TABLE will finish with error.");
return 0;
} }
static void static void
...@@ -2487,7 +2496,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) ...@@ -2487,7 +2496,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all)
thd->reset_binlog_for_next_statement(); thd->reset_binlog_for_next_statement();
DBUG_RETURN(error); DBUG_RETURN(error);
} }
if (!wsrep_emulate_bin_log && Event_log::check_write_error(thd)) if (!wsrep_emulate_bin_log && MYSQL_BIN_LOG::check_write_error(thd))
{ {
/* /*
"all == true" means that a "rollback statement" triggered the error and "all == true" means that a "rollback statement" triggered the error and
...@@ -2552,7 +2561,7 @@ void binlog_reset_cache(THD *thd) ...@@ -2552,7 +2561,7 @@ void binlog_reset_cache(THD *thd)
} }
void Event_log::set_write_error(THD *thd, bool is_transactional) void MYSQL_BIN_LOG::set_write_error(THD *thd, bool is_transactional)
{ {
DBUG_ENTER("MYSQL_BIN_LOG::set_write_error"); DBUG_ENTER("MYSQL_BIN_LOG::set_write_error");
...@@ -2592,7 +2601,7 @@ void Event_log::set_write_error(THD *thd, bool is_transactional) ...@@ -2592,7 +2601,7 @@ void Event_log::set_write_error(THD *thd, bool is_transactional)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
bool Event_log::check_write_error(THD *thd) bool MYSQL_BIN_LOG::check_write_error(THD *thd)
{ {
DBUG_ENTER("MYSQL_BIN_LOG::check_write_error"); DBUG_ENTER("MYSQL_BIN_LOG::check_write_error");
...@@ -3806,9 +3815,9 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg, ...@@ -3806,9 +3815,9 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg,
} }
bool Event_log::open(enum cache_type io_cache_type_arg) bool Event_log::open(enum cache_type io_cache_type_arg, size_t buffer_size)
{ {
bool error= init_io_cache(&log_file, -1, LOG_BIN_IO_SIZE, io_cache_type_arg, bool error= init_io_cache(&log_file, -1, buffer_size, io_cache_type_arg,
0, 0, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)); 0, 0, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL));
log_state= LOG_OPENED; log_state= LOG_OPENED;
...@@ -6395,9 +6404,14 @@ static online_alter_cache_data *binlog_setup_cache_data(MEM_ROOT *root, TABLE_SH ...@@ -6395,9 +6404,14 @@ static online_alter_cache_data *binlog_setup_cache_data(MEM_ROOT *root, TABLE_SH
{ {
static ulong online_alter_cache_use= 0, online_alter_cache_disk_use= 0; static ulong online_alter_cache_use= 0, online_alter_cache_disk_use= 0;
my_off_t file_size= SIZE_T_MAX; // maximum possible cache size
size_t cache_size= binlog_cache_size;
DBUG_EXECUTE_IF("online_alter_small_cache_1",
cache_size= file_size= IO_SIZE;);
auto cache= new (root) online_alter_cache_data(); auto cache= new (root) online_alter_cache_data();
if (!cache || open_cached_file(&cache->cache_log, mysql_tmpdir, if (!cache || open_cached_file(&cache->cache_log, mysql_tmpdir,
LOG_PREFIX, (size_t)binlog_cache_size, MYF(MY_WME))) LOG_PREFIX, cache_size, MYF(MY_WME)))
{ {
delete cache; delete cache;
return NULL; return NULL;
...@@ -6407,10 +6421,8 @@ static online_alter_cache_data *binlog_setup_cache_data(MEM_ROOT *root, TABLE_SH ...@@ -6407,10 +6421,8 @@ static online_alter_cache_data *binlog_setup_cache_data(MEM_ROOT *root, TABLE_SH
cache->hton= share->db_type(); cache->hton= share->db_type();
cache->sink_log= share->online_alter_binlog; cache->sink_log= share->online_alter_binlog;
my_off_t binlog_max_size= SIZE_T_MAX; // maximum possible cache size
DBUG_EXECUTE_IF("online_alter_small_cache", binlog_max_size= 4096;);
cache->set_binlog_cache_info(binlog_max_size, cache->set_binlog_cache_info(file_size,
&online_alter_cache_use, &online_alter_cache_use,
&online_alter_cache_disk_use); &online_alter_cache_disk_use);
cache->store_prev_position(); cache->store_prev_position();
...@@ -6550,7 +6562,8 @@ Event_log::flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event, ...@@ -6550,7 +6562,8 @@ Event_log::flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event,
if (writer.write(pending)) if (writer.write(pending))
{ {
set_write_error(thd, is_transactional); set_write_error(thd, is_transactional);
if (check_write_error(thd) && cache_data && if (dynamic_cast<MYSQL_BIN_LOG*>(this) &&
MYSQL_BIN_LOG::check_write_error(thd) && cache_data &&
stmt_has_updated_non_trans_table(thd)) stmt_has_updated_non_trans_table(thd))
cache_data->set_incident(); cache_data->set_incident();
delete pending; delete pending;
...@@ -7696,7 +7709,6 @@ class CacheWriter: public Log_event_writer ...@@ -7696,7 +7709,6 @@ class CacheWriter: public Log_event_writer
static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit) static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit)
{ {
DBUG_ENTER("binlog_online_alter_end_trans"); DBUG_ENTER("binlog_online_alter_end_trans");
int error= 0;
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
if (thd->online_alter_cache_list.empty()) if (thd->online_alter_cache_list.empty())
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -7705,12 +7717,22 @@ static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit) ...@@ -7705,12 +7717,22 @@ static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit)
for (auto &cache: thd->online_alter_cache_list) for (auto &cache: thd->online_alter_cache_list)
{ {
int error= 0;
auto *binlog= cache.sink_log; auto *binlog= cache.sink_log;
DBUG_ASSERT(binlog); DBUG_ASSERT(binlog);
if (binlog->get_write_error())
continue;
bool non_trans= cache.hton->flags & HTON_NO_ROLLBACK // Aria bool non_trans= cache.hton->flags & HTON_NO_ROLLBACK // Aria
|| !cache.hton->rollback; || !cache.hton->rollback;
bool do_commit= (commit && is_ending_transaction) || non_trans; bool do_commit= (commit && is_ending_transaction) || non_trans;
// Ignore any potential error on the DML side. It should be handled by
// the ALTER TABLE side.
Dummy_error_handler dh;
thd->push_internal_handler(&dh);
if (commit || non_trans) if (commit || non_trans)
{ {
// Do not set STMT_END for last event to leave table open in altering thd // Do not set STMT_END for last event to leave table open in altering thd
...@@ -7729,6 +7751,9 @@ static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit) ...@@ -7729,6 +7751,9 @@ static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit)
mysql_mutex_lock(binlog->get_log_lock()); mysql_mutex_lock(binlog->get_log_lock());
error= binlog->write_cache_raw(thd, &cache.cache_log); error= binlog->write_cache_raw(thd, &cache.cache_log);
mysql_mutex_unlock(binlog->get_log_lock()); mysql_mutex_unlock(binlog->get_log_lock());
if (unlikely(error))
binlog->set_write_error(my_errno);
} }
} }
else if (!commit) // rollback else if (!commit) // rollback
...@@ -7742,14 +7767,14 @@ static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit) ...@@ -7742,14 +7767,14 @@ static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit)
cache.store_prev_position(); cache.store_prev_position();
} }
thd->pop_internal_handler();
if (error) if (error)
{ {
my_error(ER_ERROR_ON_WRITE, MYF(ME_ERROR_LOG), push_warning_printf(thd, Sql_state_errno_level::WARN_LEVEL_WARN,
binlog->get_name(), errno); ER_ERROR_ON_WRITE, ER_THD(thd, ER_ERROR_ON_WRITE),
binlog_online_alter_cleanup(thd->online_alter_cache_list, binlog->get_name(), errno);
is_ending_transaction); DBUG_ASSERT(binlog->get_write_error());
DBUG_RETURN(error);
} }
} }
...@@ -7759,7 +7784,7 @@ static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit) ...@@ -7759,7 +7784,7 @@ static int binlog_online_alter_end_trans(THD *thd, bool all, bool commit)
for (TABLE *table= thd->open_tables; table; table= table->next) for (TABLE *table= thd->open_tables; table; table= table->next)
table->online_alter_cache= NULL; table->online_alter_cache= NULL;
#endif // HAVE_REPLICATION #endif // HAVE_REPLICATION
DBUG_RETURN(error); DBUG_RETURN(0);
} }
SAVEPOINT** find_savepoint_in_list(THD *thd, LEX_CSTRING name, SAVEPOINT** find_savepoint_in_list(THD *thd, LEX_CSTRING name,
...@@ -12366,6 +12391,11 @@ get_gtid_list_event(IO_CACHE *cache, Gtid_list_log_event **out_gtid_list) ...@@ -12366,6 +12391,11 @@ get_gtid_list_event(IO_CACHE *cache, Gtid_list_log_event **out_gtid_list)
return errormsg; return errormsg;
} }
void Cache_flip_event_log::set_write_error(THD *thd, bool is_transactional)
{
set_write_error(my_errno);
}
struct st_mysql_storage_engine binlog_storage_engine= struct st_mysql_storage_engine binlog_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION }; { MYSQL_HANDLERTON_INTERFACE_VERSION };
......
...@@ -400,8 +400,7 @@ class Event_log: public MYSQL_LOG ...@@ -400,8 +400,7 @@ class Event_log: public MYSQL_LOG
int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event, int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event,
binlog_cache_data *cache_data, binlog_cache_data *cache_data,
bool is_transactional); bool is_transactional);
void set_write_error(THD *thd, bool is_transactional); virtual void set_write_error(THD *thd, bool is_transactional) = 0;
static bool check_write_error(THD *thd);
int write_cache(THD *thd, IO_CACHE *cache); int write_cache(THD *thd, IO_CACHE *cache);
int write_cache_raw(THD *thd, IO_CACHE *cache); int write_cache_raw(THD *thd, IO_CACHE *cache);
char* get_name() { return name; } char* get_name() { return name; }
...@@ -420,7 +419,8 @@ class Event_log: public MYSQL_LOG ...@@ -420,7 +419,8 @@ class Event_log: public MYSQL_LOG
MY_MUTEX_INIT_SLOW); MY_MUTEX_INIT_SLOW);
} }
bool open(enum cache_type io_cache_type_arg); bool open(enum cache_type io_cache_type_arg,
size_t buffer_size= LOG_BIN_IO_SIZE);
virtual IO_CACHE *get_log_file() { return &log_file; } virtual IO_CACHE *get_log_file() { return &log_file; }
longlong write_description_event(enum_binlog_checksum_alg checksum_alg, longlong write_description_event(enum_binlog_checksum_alg checksum_alg,
...@@ -445,17 +445,20 @@ class Event_log: public MYSQL_LOG ...@@ -445,17 +445,20 @@ class Event_log: public MYSQL_LOG
*/ */
class Cache_flip_event_log: public Event_log { class Cache_flip_event_log: public Event_log {
IO_CACHE alt_buf; IO_CACHE alt_buf;
IF_DBUG(public:,)
IO_CACHE *current, *alt; IO_CACHE *current, *alt;
std::atomic<uint> ref_count; std::atomic<uint> ref_count;
std::atomic<int> online_write_error;
public: public:
Cache_flip_event_log() : Event_log(), alt_buf{}, Cache_flip_event_log() : Event_log(), alt_buf{},
current(&log_file), alt(&alt_buf), ref_count(1) {} current(&log_file), alt(&alt_buf), ref_count(1),
bool open(enum cache_type io_cache_type_arg) online_write_error(0) {}
bool open(size_t buffer_size)
{ {
log_file.dir= mysql_tmpdir; log_file.dir= mysql_tmpdir;
alt_buf.dir= log_file.dir; alt_buf.dir= log_file.dir;
bool res= Event_log::open(io_cache_type_arg); bool res= Event_log::open(WRITE_CACHE);
if (res) if (res)
return res; return res;
...@@ -464,7 +467,7 @@ class Cache_flip_event_log: public Event_log { ...@@ -464,7 +467,7 @@ class Cache_flip_event_log: public Event_log {
if (!name) if (!name)
return false; return false;
res= init_io_cache(&alt_buf, -1, LOG_BIN_IO_SIZE, io_cache_type_arg, 0, 0, res= init_io_cache(&alt_buf, -1, buffer_size, WRITE_CACHE, 0, 0,
MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0; MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0;
return res; return res;
} }
...@@ -509,6 +512,17 @@ class Cache_flip_event_log: public Event_log { ...@@ -509,6 +512,17 @@ class Cache_flip_event_log: public Event_log {
delete this; delete this;
} }
} }
void set_write_error(THD *thd, bool is_transactional) override;
void set_write_error(int error)
{
online_write_error.store(error, std::memory_order_relaxed);
}
int get_write_error() const
{
return online_write_error.load(std::memory_order_relaxed);
}
private: private:
void cleanup() void cleanup()
...@@ -986,6 +1000,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log ...@@ -986,6 +1000,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log
bool write_incident(THD *thd); bool write_incident(THD *thd);
void write_binlog_checkpoint_event_already_locked(const char *name, uint len); void write_binlog_checkpoint_event_already_locked(const char *name, uint len);
bool write_table_map(THD *thd, TABLE *table, bool with_annotate); bool write_table_map(THD *thd, TABLE *table, bool with_annotate);
void set_write_error(THD *thd, bool is_transactional) override;
static bool check_write_error(THD *thd);
void start_union_events(THD *thd, query_id_t query_id_param); void start_union_events(THD *thd, query_id_t query_id_param);
void stop_union_events(THD *thd); void stop_union_events(THD *thd);
bool is_query_in_union(THD *thd, query_id_t query_id_param); bool is_query_in_union(THD *thd, query_id_t query_id_param);
......
...@@ -11662,6 +11662,14 @@ static int online_alter_read_from_binlog(THD *thd, rpl_group_info *rgi, ...@@ -11662,6 +11662,14 @@ static int online_alter_read_from_binlog(THD *thd, rpl_group_info *rgi,
thd->push_internal_handler(&hdeh); thd->push_internal_handler(&hdeh);
do do
{ {
error= log->get_write_error();
if (unlikely(error))
{
my_error(ER_IO_WRITE_ERROR, MYF(0), (ulong)error, strerror(error), "");
error= 1;
break;
}
const auto *descr_event= rgi->rli->relay_log.description_event_for_exec; const auto *descr_event= rgi->rli->relay_log.description_event_for_exec;
auto *ev= Log_event::read_log_event(log_file, descr_event, false); auto *ev= Log_event::read_log_event(log_file, descr_event, false);
error= log_file->error; error= log_file->error;
...@@ -11889,7 +11897,10 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, ...@@ -11889,7 +11897,10 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
if (!from->s->online_alter_binlog) if (!from->s->online_alter_binlog)
DBUG_RETURN(1); DBUG_RETURN(1);
from->s->online_alter_binlog->init_pthread_objects(); from->s->online_alter_binlog->init_pthread_objects();
error= from->s->online_alter_binlog->open(WRITE_CACHE);
size_t buffer_size= LOG_BIN_IO_SIZE;
DBUG_EXECUTE_IF("online_alter_small_cache_2", buffer_size= IO_SIZE;);
error= from->s->online_alter_binlog->open(buffer_size);
if (error) if (error)
{ {
...@@ -12099,6 +12110,9 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, ...@@ -12099,6 +12110,9 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
error= online_alter_read_from_binlog(thd, &rgi, binlog); error= online_alter_read_from_binlog(thd, &rgi, binlog);
// flip() makes reinit_io_cache, so it should be here
DBUG_EXECUTE_IF("online_alter_small_cache_2",
from->s->online_alter_binlog->current->end_of_file= IO_SIZE;);
DEBUG_SYNC(thd, "alter_table_online_before_lock"); DEBUG_SYNC(thd, "alter_table_online_before_lock");
int lock_error= int lock_error=
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment