summaryrefslogtreecommitdiffstats
path: root/sql/log.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/log.cc')
-rw-r--r--sql/log.cc129
1 files changed, 86 insertions, 43 deletions
diff --git a/sql/log.cc b/sql/log.cc
index d3879aad..4b9e5ebc 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1457,7 +1457,7 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, size_t query_length,
query_utime= (current_utime - thd->start_utime);
lock_utime= (thd->utime_after_lock - thd->start_utime);
my_hrtime_t current_time= { hrtime_from_time(thd->start_time) +
- thd->start_time_sec_part + query_utime };
+ thd->start_time_sec_part };
if (!query || thd->get_command() == COM_STMT_PREPARE)
{
@@ -2539,6 +2539,23 @@ bool MYSQL_BIN_LOG::check_write_error(THD *thd)
}
+/*
+ Check if there was an error while writing the statement cache.
+ If the cache content is corrupt due to an error, we should write an incident
+ event to the binlog rather than write corrupt data to it.
+*/
+bool
+MYSQL_BIN_LOG::check_cache_error(THD *thd, binlog_cache_data *cache_data)
+{
+ if (!cache_data)
+ return false;
+ if (check_write_error(thd))
+ return true;
+ if (!cache_data->empty() && cache_data->cache_log.error)
+ return true;
+ return false;
+}
+
/**
@note
How do we handle this (unlikely but legal) case:
@@ -3796,7 +3813,6 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
bool null_created_arg,
bool need_mutex)
{
- File file= -1;
xid_count_per_binlog *new_xid_list_entry= NULL, *b;
DBUG_ENTER("MYSQL_BIN_LOG::open");
@@ -4192,8 +4208,6 @@ err:
sql_print_error(fatal_log_error, (name) ? name : log_name, tmp_errno);
if (new_xid_list_entry)
delete new_xid_list_entry;
- if (file >= 0)
- mysql_file_close(file, MYF(0));
close(LOG_CLOSE_INDEX);
DBUG_RETURN(1);
}
@@ -5465,8 +5479,6 @@ int MYSQL_BIN_LOG::new_file_without_locking()
/**
Start writing to a new log file or reopen the old file.
- @param need_lock Set to 1 if caller has not locked LOCK_log
-
@retval
nonzero - error
@@ -6269,12 +6281,13 @@ bool THD::binlog_write_table_map(TABLE *table, bool with_annotate)
int error= 1;
bool is_transactional= table->file->row_logging_has_trans;
DBUG_ENTER("THD::binlog_write_table_map");
- DBUG_PRINT("enter", ("table: %p (%s: #%lu)",
+ DBUG_PRINT("enter", ("table: %p (%s: #%llu)",
table, table->s->table_name.str,
table->s->table_map_id));
/* Pre-conditions */
- DBUG_ASSERT(table->s->table_map_id != ULONG_MAX);
+ DBUG_ASSERT((table->s->table_map_id & MAX_TABLE_MAP_ID) != UINT32_MAX &&
+ (table->s->table_map_id & MAX_TABLE_MAP_ID) != 0);
/* Ensure that all events in a GTID group are in the same cache */
if (variables.option_bits & OPTION_GTID_BEGIN)
@@ -6315,7 +6328,7 @@ write_err:
engines, data is written to table but writing to binary log failed. In
these scenarios rollback is not possible. Hence report an incident.
*/
- if (mysql_bin_log.check_write_error(this) && cache_data &&
+ if (mysql_bin_log.check_cache_error(this, cache_data) &&
lex->stmt_accessed_table(LEX::STMT_WRITES_NON_TRANS_TABLE) &&
table->current_lock == F_WRLCK)
cache_data->set_incident();
@@ -6447,20 +6460,37 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd,
/*
Write pending event to the cache.
*/
+#ifndef DBUG_OFF
+ bool clear_dbug= false;
+#endif
DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending",
- {DBUG_SET("+d,simulate_file_write_error");});
+ {
+ if (my_b_tell(&cache_data->cache_log) > 10000)
+ {
+ DBUG_SET("+d,simulate_file_write_error");
+ clear_dbug= true;
+ }
+ });
if (writer.write(pending))
{
set_write_error(thd, is_transactional);
- if (check_write_error(thd) && cache_data &&
+ if (check_cache_error(thd, cache_data) &&
stmt_has_updated_non_trans_table(thd))
cache_data->set_incident();
delete pending;
cache_data->set_pending(NULL);
DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending",
- {DBUG_SET("-d,simulate_file_write_error");});
+ {
+ if (clear_dbug)
+ DBUG_SET("-d,simulate_file_write_error");
+ });
DBUG_RETURN(1);
}
+ DBUG_EXECUTE_IF("simulate_disk_full_at_flush_pending",
+ {
+ if (clear_dbug)
+ DBUG_SET("-d,simulate_file_write_error");
+ });
delete pending;
}
@@ -6950,18 +6980,12 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
BINLOG_USER_VAR_EVENT *user_var_event;
get_dynamic(&thd->user_var_events,(uchar*) &user_var_event, i);
- /* setting flags for user var log event */
- uchar flags= User_var_log_event::UNDEF_F;
- if (user_var_event->unsigned_flag)
- flags|= User_var_log_event::UNSIGNED_F;
-
User_var_log_event e(thd, user_var_event->user_var_event->name.str,
user_var_event->user_var_event->name.length,
user_var_event->value,
user_var_event->length,
- user_var_event->type,
- user_var_event->charset_number,
- flags,
+ user_var_event->th->user_var_log_event_data_type(
+ user_var_event->charset_number),
using_trans,
direct);
if (write_event(&e, cache_data, file))
@@ -7057,7 +7081,7 @@ err:
if (unlikely(error))
{
set_write_error(thd, is_trans_cache);
- if (check_write_error(thd) && cache_data &&
+ if (check_cache_error(thd, cache_data) &&
stmt_has_updated_non_trans_table(thd))
cache_data->set_incident();
}
@@ -8751,13 +8775,10 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader)
DEBUG_SYNC(leader->thd, "commit_loop_entry_commit_ordered");
++num_commits;
+ set_current_thd(current->thd);
if (current->cache_mngr->using_xa && likely(!current->error) &&
!DBUG_IF("skip_commit_ordered"))
- {
- mysql_mutex_lock(&current->thd->LOCK_thd_data);
run_commit_ordered(current->thd, current->all);
- mysql_mutex_unlock(&current->thd->LOCK_thd_data);
- }
current->thd->wakeup_subsequent_commits(current->error);
/*
@@ -8774,6 +8795,7 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader)
}
current= next;
}
+ set_current_thd(leader->thd);
DEBUG_SYNC(leader->thd, "commit_after_group_run_commit_ordered");
mysql_mutex_unlock(&LOCK_commit_ordered);
DEBUG_SYNC(leader->thd, "commit_after_group_release_commit_ordered");
@@ -8794,6 +8816,20 @@ MYSQL_BIN_LOG::write_transaction_or_stmt(group_commit_entry *entry,
DBUG_ENTER("MYSQL_BIN_LOG::write_transaction_or_stmt");
+ /*
+ An error in the trx_cache will truncate the cache to the last good
+ statement, it won't leave a lingering error. Assert that this holds.
+ */
+ DBUG_ASSERT(!(entry->using_trx_cache && !mngr->trx_cache.empty() &&
+ mngr->get_binlog_cache_log(TRUE)->error));
+ /*
+ An error in the stmt_cache would be caught on the higher level and result
+ in an incident event being written over a (possibly corrupt) cache content.
+ Assert that this holds.
+ */
+ DBUG_ASSERT(!(entry->using_stmt_cache && !mngr->stmt_cache.empty() &&
+ mngr->get_binlog_cache_log(FALSE)->error));
+
if (write_gtid_event(entry->thd, is_prepared_xa(entry->thd),
entry->using_trx_cache, commit_id,
has_xid, entry->ro_1pc))
@@ -11136,7 +11172,7 @@ Recovery_context::Recovery_context() :
prev_event_pos(0),
last_gtid_standalone(false), last_gtid_valid(false), last_gtid_no2pc(false),
last_gtid_engines(0),
- do_truncate(rpl_semi_sync_slave_enabled),
+ do_truncate(repl_semisync_slave.get_slave_enabled()),
truncate_validated(false), truncate_reset_done(false),
truncate_set_in_1st(false), id_binlog(MAX_binlog_id),
checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF), gtid_maybe_to_truncate(NULL)
@@ -11945,14 +11981,21 @@ set_binlog_snapshot_file(const char *src)
void
TC_LOG_BINLOG::set_status_variables(THD *thd)
{
- binlog_cache_mngr *cache_mngr;
+ bool have_snapshot= false;
if (thd && opt_bin_log)
- cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
- else
- cache_mngr= 0;
+ {
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ auto cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+ have_snapshot= cache_mngr && cache_mngr->last_commit_pos_file[0];
+ if (have_snapshot)
+ {
+ set_binlog_snapshot_file(cache_mngr->last_commit_pos_file);
+ binlog_snapshot_position= cache_mngr->last_commit_pos_offset;
+ }
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ }
- bool have_snapshot= (cache_mngr && cache_mngr->last_commit_pos_file[0] != 0);
mysql_mutex_lock(&LOCK_commit_ordered);
binlog_status_var_num_commits= this->num_commits;
binlog_status_var_num_group_commits= this->num_group_commits;
@@ -11967,12 +12010,6 @@ TC_LOG_BINLOG::set_status_variables(THD *thd)
binlog_status_group_commit_trigger_timeout= this->group_commit_trigger_timeout;
binlog_status_group_commit_trigger_lock_wait= this->group_commit_trigger_lock_wait;
mysql_mutex_unlock(&LOCK_prepare_ordered);
-
- if (have_snapshot)
- {
- set_binlog_snapshot_file(cache_mngr->last_commit_pos_file);
- binlog_snapshot_position= cache_mngr->last_commit_pos_offset;
- }
}
@@ -12083,6 +12120,15 @@ IO_CACHE *wsrep_get_cache(THD * thd, bool is_transactional)
return NULL;
}
+bool wsrep_is_binlog_cache_empty(THD *thd)
+{
+ binlog_cache_mngr *cache_mngr=
+ (binlog_cache_mngr *) thd_get_ha_data(thd, binlog_hton);
+ if (cache_mngr)
+ return cache_mngr->trx_cache.empty() && cache_mngr->stmt_cache.empty();
+ return true;
+}
+
void wsrep_thd_binlog_trx_reset(THD * thd)
{
DBUG_ENTER("wsrep_thd_binlog_trx_reset");
@@ -12143,12 +12189,9 @@ void wsrep_register_binlog_handler(THD *thd, bool trx)
/*
Set an implicit savepoint in order to be able to truncate a trx-cache.
*/
- if (cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
- {
- my_off_t pos= 0;
- binlog_trans_log_savepos(thd, &pos);
- cache_mngr->trx_cache.set_prev_position(pos);
- }
+ my_off_t pos= 0;
+ binlog_trans_log_savepos(thd, &pos);
+ cache_mngr->trx_cache.set_prev_position(pos);
/*
Set callbacks in order to be able to call commmit or rollback.