diff options
Diffstat (limited to 'sql/log.cc')
-rw-r--r-- | sql/log.cc | 129 |
1 files changed, 86 insertions, 43 deletions
@@ -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(¤t->thd->LOCK_thd_data); run_commit_ordered(current->thd, current->all); - mysql_mutex_unlock(¤t->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. |