diff --git a/sql/binlog.cc b/sql/binlog.cc index bec6a1f6c19..6d4a8b8c2fd 100644 --- a/sql/binlog.cc +++ b/sql/binlog.cc @@ -3639,7 +3639,9 @@ static bool is_number(const char *str, ulong *res, bool allow_wildcards) { nonzero if not possible to get unique filename. */ -static int find_uniq_filename(char *name, uint32 new_index_number) { +static int find_uniq_filename( + char *name, uint32 new_index_number, + std::pair *max_cur_index_number = NULL) { uint i; char buff[FN_REFLEN], ext_buf[FN_REFLEN]; MY_DIR *dir_info = nullptr; @@ -3657,21 +3659,25 @@ static int find_uniq_filename(char *name, uint32 new_index_number) { *end = '.'; length = (size_t)(end - start + 1); - if ((DBUG_EVALUATE_IF( - "error_unique_log_filename", 1, - !(dir_info = - my_dir(buff, MYF(MY_DONT_SORT)))))) { // This shouldn't happen - my_stpcpy(end, ".1"); // use name+1 - return 1; - } - file_info = dir_info->dir_entry; - for (i = dir_info->number_off_files; i--; file_info++) { - if (strncmp(file_info->name, start, length) == 0 && - is_number(file_info->name + length, &number, false)) { - max_found = std::max(max_found, number); + if (max_cur_index_number && max_cur_index_number->first) { + max_found = max_cur_index_number->first; + } else { + if ((DBUG_EVALUATE_IF( + "error_unique_log_filename", 1, + !(dir_info = my_dir( + buff, MYF(MY_DONT_SORT)))))) { // This shouldn't happen + my_stpcpy(end, ".1"); // use name+1 + return 1; } + file_info = dir_info->dir_entry; + for (i = dir_info->number_off_files; i--; file_info++) { + if (strncmp(file_info->name, start, length) == 0 && + is_number(file_info->name + length, &number, false)) { + max_found = std::max(max_found, number); + } + } + my_dirend(dir_info); } - my_dirend(dir_info); /* check if reached the maximum possible extension number */ if (max_found >= MAX_LOG_UNIQUE_FN_EXT) { @@ -3713,6 +3719,8 @@ static int find_uniq_filename(char *name, uint32 new_index_number) { goto end; } + if (max_cur_index_number) max_cur_index_number->second = next; + /* print warning if reaching the end of available extensions. */ if (next > MAX_ALLOWED_FN_EXT_RESET_MASTER) LogErr(WARNING_LEVEL, ER_BINLOG_FILE_EXTENSION_NUMBER_RUNNING_LOW, next, @@ -3726,7 +3734,7 @@ int MYSQL_BIN_LOG::generate_new_name(char *new_name, const char *log_name, uint32 new_index_number) { fn_format(new_name, log_name, mysql_data_home, "", 4); if (!fn_ext(log_name)[0]) { - if (find_uniq_filename(new_name, new_index_number)) { + if (find_uniq_filename(new_name, new_index_number, &max_cur_index_number)) { if (current_thd != nullptr) my_printf_error(ER_NO_UNIQUE_LOGFILE, ER_THD(current_thd, ER_NO_UNIQUE_LOGFILE), @@ -5093,7 +5101,11 @@ bool MYSQL_BIN_LOG::open_binlog( DBUG_EXECUTE_IF("crash_create_after_update_index", DBUG_SUICIDE();); } + atomic_log_state = LOG_OPENED; + + max_cur_index_number.first = max_cur_index_number.second; + /* At every rotate memorize the last transaction counter state to use it as offset at logging the transaction logical timestamps. @@ -5106,6 +5118,9 @@ bool MYSQL_BIN_LOG::open_binlog( return false; err: + + max_cur_index_number = {0, 0}; + if (is_inited_purge_index_file()) purge_index_entry(nullptr, nullptr, need_lock_index); close_purge_index_file(); @@ -5647,6 +5662,9 @@ bool MYSQL_BIN_LOG::reset_logs(THD *thd, bool delete_only) { sid_lock = previous_gtid_set_relaylog->get_sid_map()->get_sid_lock(); else sid_lock = global_sid_lock; + + max_cur_index_number = {0, 0}; + sid_lock->wrlock(); /* Save variables so that we can reopen the log */ diff --git a/sql/binlog.h b/sql/binlog.h index f0df7014f8a..5fe715348fe 100644 --- a/sql/binlog.h +++ b/sql/binlog.h @@ -292,6 +292,20 @@ class MYSQL_BIN_LOG : public TC_LOG { int generate_new_name(char *new_name, const char *log_name, uint32 new_index_number = 0); + /* + For faster binlog rotate. + It is introduced so that binlog rotate need not iterate all binlog files + to find the next index number for the new logfile. + + @first: The maximum index number used. + If nonzero, the next index number is curr_max_index_number.first + 1. + + @second: The new maximum index number that is not yet written to @first. + It is updated when creating a new logfile. Note that its value is written to + @first only when the new logfile is successfully opened. + */ + std::pair max_cur_index_number; + protected: /** @brief Notifies waiting threads that binary log has been updated