Fixes bug #13377. Added code to close active log files in case
of log reset condition. sql/log.cc: Added references counter of binlog readers to wait for closing opened log files by al readers for binary log reset. sql/slave.cc: Added a code to close opened relay log files, when they are not used anymore. sql/sql_class.h: Added declarations to maintain references count of binlog readers. Added reset log wait condition. sql/sql_repl.cc: Added code to close active log files in case of log reset condition.
This commit is contained in:
parent
b2ee385ff3
commit
3398cb233a
67
sql/log.cc
67
sql/log.cc
@ -353,7 +353,7 @@ MYSQL_LOG::MYSQL_LOG()
|
|||||||
:bytes_written(0), last_time(0), query_start(0), name(0),
|
:bytes_written(0), last_time(0), query_start(0), name(0),
|
||||||
file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0), inited(0),
|
file_id(1), open_count(1), log_type(LOG_CLOSED), write_error(0), inited(0),
|
||||||
need_start_event(1), prepared_xids(0), description_event_for_exec(0),
|
need_start_event(1), prepared_xids(0), description_event_for_exec(0),
|
||||||
description_event_for_queue(0)
|
description_event_for_queue(0), readers_count(0), reset_pending(false)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We don't want to initialize LOCK_Log here as such initialization depends on
|
We don't want to initialize LOCK_Log here as such initialization depends on
|
||||||
@ -379,7 +379,9 @@ void MYSQL_LOG::cleanup()
|
|||||||
delete description_event_for_exec;
|
delete description_event_for_exec;
|
||||||
(void) pthread_mutex_destroy(&LOCK_log);
|
(void) pthread_mutex_destroy(&LOCK_log);
|
||||||
(void) pthread_mutex_destroy(&LOCK_index);
|
(void) pthread_mutex_destroy(&LOCK_index);
|
||||||
|
(void) pthread_mutex_destroy(&LOCK_readers);
|
||||||
(void) pthread_cond_destroy(&update_cond);
|
(void) pthread_cond_destroy(&update_cond);
|
||||||
|
(void) pthread_cond_destroy(&reset_cond);
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -424,7 +426,9 @@ void MYSQL_LOG::init_pthread_objects()
|
|||||||
inited= 1;
|
inited= 1;
|
||||||
(void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
|
(void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW);
|
||||||
(void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
|
(void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW);
|
||||||
|
(void) pthread_mutex_init(&LOCK_readers, MY_MUTEX_INIT_SLOW);
|
||||||
(void) pthread_cond_init(&update_cond, 0);
|
(void) pthread_cond_init(&update_cond, 0);
|
||||||
|
(void) pthread_cond_init(&reset_cond, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *MYSQL_LOG::generate_name(const char *log_name,
|
const char *MYSQL_LOG::generate_name(const char *log_name,
|
||||||
@ -927,6 +931,13 @@ bool MYSQL_LOG::reset_logs(THD* thd)
|
|||||||
*/
|
*/
|
||||||
pthread_mutex_lock(&LOCK_log);
|
pthread_mutex_lock(&LOCK_log);
|
||||||
pthread_mutex_lock(&LOCK_index);
|
pthread_mutex_lock(&LOCK_index);
|
||||||
|
|
||||||
|
/*
|
||||||
|
we need one more lock to block attempts to open a log while
|
||||||
|
we are waiting untill all log files will be closed
|
||||||
|
*/
|
||||||
|
pthread_mutex_lock(&LOCK_readers);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following mutex is needed to ensure that no threads call
|
The following mutex is needed to ensure that no threads call
|
||||||
'delete thd' as we would then risk missing a 'rollback' from this
|
'delete thd' as we would then risk missing a 'rollback' from this
|
||||||
@ -949,6 +960,19 @@ bool MYSQL_LOG::reset_logs(THD* thd)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_pending = true;
|
||||||
|
/*
|
||||||
|
send update signal just in case so that all reader threads waiting
|
||||||
|
for log update will leave wait condition
|
||||||
|
*/
|
||||||
|
signal_update();
|
||||||
|
/*
|
||||||
|
if there are active readers wait until all of them will
|
||||||
|
release opened files
|
||||||
|
*/
|
||||||
|
if (readers_count)
|
||||||
|
pthread_cond_wait(&reset_cond, &LOCK_log);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
my_delete(linfo.log_file_name, MYF(MY_WME));
|
my_delete(linfo.log_file_name, MYF(MY_WME));
|
||||||
@ -967,7 +991,10 @@ bool MYSQL_LOG::reset_logs(THD* thd)
|
|||||||
my_free((gptr) save_name, MYF(0));
|
my_free((gptr) save_name, MYF(0));
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
reset_pending = false;
|
||||||
|
|
||||||
(void) pthread_mutex_unlock(&LOCK_thread_count);
|
(void) pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
|
pthread_mutex_unlock(&LOCK_readers);
|
||||||
pthread_mutex_unlock(&LOCK_index);
|
pthread_mutex_unlock(&LOCK_index);
|
||||||
pthread_mutex_unlock(&LOCK_log);
|
pthread_mutex_unlock(&LOCK_log);
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
@ -2038,6 +2065,10 @@ void MYSQL_LOG::wait_for_update(THD* thd, bool is_slave)
|
|||||||
{
|
{
|
||||||
const char *old_msg;
|
const char *old_msg;
|
||||||
DBUG_ENTER("wait_for_update");
|
DBUG_ENTER("wait_for_update");
|
||||||
|
|
||||||
|
if (reset_pending)
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
old_msg= thd->enter_cond(&update_cond, &LOCK_log,
|
old_msg= thd->enter_cond(&update_cond, &LOCK_log,
|
||||||
is_slave ?
|
is_slave ?
|
||||||
"Has read all relay log; waiting for the slave I/O "
|
"Has read all relay log; waiting for the slave I/O "
|
||||||
@ -2288,6 +2319,40 @@ void MYSQL_LOG::signal_update()
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MYSQL_LOG::readers_addref()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
currently readers_addref and readers_release are necessary
|
||||||
|
only for __WIN__ build to wait untill readers will close
|
||||||
|
opened log files before reset.
|
||||||
|
There is no necessity for this on *nix, since it allows to
|
||||||
|
delete opened files, however it is more clean way to wait
|
||||||
|
untill all files will be closed on *nix as well.
|
||||||
|
If decided, the following #ifdef section is to be removed.
|
||||||
|
*/
|
||||||
|
#ifdef __WIN__
|
||||||
|
DBUG_ENTER("MYSQL_LOG::reader_addref");
|
||||||
|
pthread_mutex_lock(&LOCK_log);
|
||||||
|
pthread_mutex_lock(&LOCK_readers);
|
||||||
|
readers_count++;
|
||||||
|
pthread_mutex_unlock(&LOCK_readers);
|
||||||
|
pthread_mutex_unlock(&LOCK_log);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MYSQL_LOG::readers_release()
|
||||||
|
{
|
||||||
|
#ifdef __WIN__
|
||||||
|
DBUG_ENTER("MYSQL_LOG::reader_release");
|
||||||
|
pthread_mutex_lock(&LOCK_log);
|
||||||
|
readers_count--;
|
||||||
|
if (!readers_count)
|
||||||
|
pthread_cond_broadcast(&reset_cond);
|
||||||
|
pthread_mutex_unlock(&LOCK_log);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __NT__
|
#ifdef __NT__
|
||||||
void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
|
void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
|
||||||
|
17
sql/slave.cc
17
sql/slave.cc
@ -3615,6 +3615,15 @@ err:
|
|||||||
pthread_mutex_lock(&mi->run_lock);
|
pthread_mutex_lock(&mi->run_lock);
|
||||||
mi->slave_running = 0;
|
mi->slave_running = 0;
|
||||||
mi->io_thd = 0;
|
mi->io_thd = 0;
|
||||||
|
|
||||||
|
/* Close log file and free buffers */
|
||||||
|
if (mi->rli.cur_log_fd >= 0)
|
||||||
|
{
|
||||||
|
end_io_cache(&mi->rli.cache_buf);
|
||||||
|
my_close(mi->rli.cur_log_fd, MYF(MY_WME));
|
||||||
|
mi->rli.cur_log_fd= -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Forget the relay log's format */
|
/* Forget the relay log's format */
|
||||||
delete mi->rli.relay_log.description_event_for_queue;
|
delete mi->rli.relay_log.description_event_for_queue;
|
||||||
mi->rli.relay_log.description_event_for_queue= 0;
|
mi->rli.relay_log.description_event_for_queue= 0;
|
||||||
@ -3831,6 +3840,14 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
|
|||||||
rli->cached_charset_invalidate();
|
rli->cached_charset_invalidate();
|
||||||
rli->save_temporary_tables = thd->temporary_tables;
|
rli->save_temporary_tables = thd->temporary_tables;
|
||||||
|
|
||||||
|
/* Close log file and free buffers if it's already open */
|
||||||
|
if (rli->cur_log_fd >= 0)
|
||||||
|
{
|
||||||
|
end_io_cache(&rli->cache_buf);
|
||||||
|
my_close(rli->cur_log_fd, MYF(MY_WME));
|
||||||
|
rli->cur_log_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: see if we can do this conditionally in next_event() instead
|
TODO: see if we can do this conditionally in next_event() instead
|
||||||
to avoid unneeded position re-init
|
to avoid unneeded position re-init
|
||||||
|
@ -189,8 +189,11 @@ class MYSQL_LOG: public TC_LOG
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */
|
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */
|
||||||
pthread_mutex_t LOCK_log, LOCK_index;
|
pthread_mutex_t LOCK_log, LOCK_index, LOCK_readers;
|
||||||
pthread_cond_t update_cond;
|
pthread_cond_t update_cond;
|
||||||
|
pthread_cond_t reset_cond;
|
||||||
|
bool reset_pending;
|
||||||
|
int readers_count;
|
||||||
ulonglong bytes_written;
|
ulonglong bytes_written;
|
||||||
time_t last_time,query_start;
|
time_t last_time,query_start;
|
||||||
IO_CACHE log_file;
|
IO_CACHE log_file;
|
||||||
@ -334,6 +337,9 @@ public:
|
|||||||
int purge_logs_before_date(time_t purge_time);
|
int purge_logs_before_date(time_t purge_time);
|
||||||
int purge_first_log(struct st_relay_log_info* rli, bool included);
|
int purge_first_log(struct st_relay_log_info* rli, bool included);
|
||||||
bool reset_logs(THD* thd);
|
bool reset_logs(THD* thd);
|
||||||
|
inline bool is_reset_pending() { return reset_pending; }
|
||||||
|
void readers_addref();
|
||||||
|
void readers_release();
|
||||||
void close(uint exiting);
|
void close(uint exiting);
|
||||||
|
|
||||||
// iterating through the log index file
|
// iterating through the log index file
|
||||||
|
@ -372,6 +372,11 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Call readers_addref before opening log to track count
|
||||||
|
of binlog readers
|
||||||
|
*/
|
||||||
|
mysql_bin_log.readers_addref();
|
||||||
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0)
|
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0)
|
||||||
{
|
{
|
||||||
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
|
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
|
||||||
@ -569,7 +574,8 @@ impossible position";
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!(flags & BINLOG_DUMP_NON_BLOCK) &&
|
if (!(flags & BINLOG_DUMP_NON_BLOCK) &&
|
||||||
mysql_bin_log.is_active(log_file_name))
|
mysql_bin_log.is_active(log_file_name) &&
|
||||||
|
!mysql_bin_log.is_reset_pending())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Block until there is more data in the log
|
Block until there is more data in the log
|
||||||
@ -683,6 +689,13 @@ impossible position";
|
|||||||
{
|
{
|
||||||
bool loop_breaker = 0;
|
bool loop_breaker = 0;
|
||||||
// need this to break out of the for loop from switch
|
// need this to break out of the for loop from switch
|
||||||
|
|
||||||
|
// if we are going to switch log file anyway, close current log first
|
||||||
|
end_io_cache(&log);
|
||||||
|
(void) my_close(file, MYF(MY_WME));
|
||||||
|
// decrease reference count of binlog readers
|
||||||
|
mysql_bin_log.readers_release();
|
||||||
|
|
||||||
thd->proc_info = "Finished reading one binlog; switching to next binlog";
|
thd->proc_info = "Finished reading one binlog; switching to next binlog";
|
||||||
switch (mysql_bin_log.find_next_log(&linfo, 1)) {
|
switch (mysql_bin_log.find_next_log(&linfo, 1)) {
|
||||||
case LOG_INFO_EOF:
|
case LOG_INFO_EOF:
|
||||||
@ -691,16 +704,25 @@ impossible position";
|
|||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
// need following call to do release on err label
|
||||||
|
mysql_bin_log.readers_addref();
|
||||||
errmsg = "could not find next log";
|
errmsg = "could not find next log";
|
||||||
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
|
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loop_breaker)
|
if (loop_breaker)
|
||||||
break;
|
{
|
||||||
|
// need following call to do release on end label
|
||||||
|
mysql_bin_log.readers_addref();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
end_io_cache(&log);
|
/*
|
||||||
(void) my_close(file, MYF(MY_WME));
|
Call readers_addref before opening log to track count
|
||||||
|
of binlog readers
|
||||||
|
*/
|
||||||
|
mysql_bin_log.readers_addref();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Call fake_rotate_event() in case the previous log (the one which
|
Call fake_rotate_event() in case the previous log (the one which
|
||||||
@ -733,6 +755,8 @@ end:
|
|||||||
|
|
||||||
end_io_cache(&log);
|
end_io_cache(&log);
|
||||||
(void)my_close(file, MYF(MY_WME));
|
(void)my_close(file, MYF(MY_WME));
|
||||||
|
// decrease reference count of binlog readers
|
||||||
|
mysql_bin_log.readers_release();
|
||||||
|
|
||||||
send_eof(thd);
|
send_eof(thd);
|
||||||
thd->proc_info = "Waiting to finalize termination";
|
thd->proc_info = "Waiting to finalize termination";
|
||||||
@ -759,6 +783,9 @@ err:
|
|||||||
pthread_mutex_unlock(&LOCK_thread_count);
|
pthread_mutex_unlock(&LOCK_thread_count);
|
||||||
if (file >= 0)
|
if (file >= 0)
|
||||||
(void) my_close(file, MYF(MY_WME));
|
(void) my_close(file, MYF(MY_WME));
|
||||||
|
// decrease reference count of binlog readers
|
||||||
|
mysql_bin_log.readers_release();
|
||||||
|
|
||||||
my_message(my_errno, errmsg, MYF(0));
|
my_message(my_errno, errmsg, MYF(0));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user