diff options
author | Luis Soares <luis.soares@sun.com> | 2010-02-03 16:56:17 +0000 |
---|---|---|
committer | Luis Soares <luis.soares@sun.com> | 2010-02-03 16:56:17 +0000 |
commit | 55aab082a957e3f20e94f791dbe44750b4b465c8 (patch) | |
tree | 0830be99ef4b6b308d020c571711d5f5a06e04f9 /sql/rpl_mi.cc | |
parent | 54fc7997e217c7556f06693f1d04caf5ce8ca36b (diff) | |
download | mariadb-git-55aab082a957e3f20e94f791dbe44750b4b465c8.tar.gz |
BUG#50364: FLUSH LOGS crashes the server (rpl.rpl_heartbeat_basic
fails in PB sporadically)
The IO thread can concurrently access the relay log IO_CACHE
while another thread is performing an FLUSH LOGS procedure.
FLUSH LOGS closes and reopens the relay log and while doing so it
(re)initializes its IO_CACHE. During this procedure the IO_CACHE
mutex is also reinitialized, which can cause problems if some
other thread (namely the IO THREAD) is concurrently accessing it
at the time .
This patch fixes the problem by extending the interface of the
flush_master_info function to also include a second paramater,
"need_relay_log_lock", stating whether the thread should grab the
relay log lock or not before actually flushing the relay log.
Also, IO thread now calls flush_master_info with this flag set
when it flushes master info with in the event read_event loop.
Finally, we also increase loop time in rpl_heartbeat_basic test
case, so that the number of calls to flush logs doubles, stressing
this part of the code a little more.
mysql-test/suite/rpl/t/rpl_heartbeat_basic.test:
Doubled the number of iterations on the FLUSH LOGS loop by
doubling the time available to perform all iterations.
sql/repl_failsafe.cc:
Updating flush_master_info call so that it uses two parameters
instead of one.
sql/rpl_mi.cc:
Updating flush_master_info call so that it uses two parameters
instead of one.
sql/rpl_mi.h:
Changed flush_master_info interface. Now takes a second parameter
instead of just one. The second parameter is: need_lock_relay_log.
sql/rpl_rli.cc:
Small fix in comment.
sql/slave.cc:
Updating flush_master_info call so that it uses two parameters
instead of one.
sql/sql_repl.cc:
Updating flush_master_info call so that it uses two parameters
instead of one.
Diffstat (limited to 'sql/rpl_mi.cc')
-rw-r--r-- | sql/rpl_mi.cc | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index e83e0ad0ba9..28b0af441f8 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -387,7 +387,7 @@ file '%s')", fname); mi->rli.is_relay_log_recovery= FALSE; // now change cache READ -> WRITE - must do this before flush_master_info reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1); - if ((error=test(flush_master_info(mi, 1)))) + if ((error=test(flush_master_info(mi, TRUE, TRUE)))) sql_print_error("Failed to flush master info file"); pthread_mutex_unlock(&mi->data_lock); DBUG_RETURN(error); @@ -413,7 +413,9 @@ err: 1 - flush master info failed 0 - all ok */ -int flush_master_info(Master_info* mi, bool flush_relay_log_cache) +int flush_master_info(Master_info* mi, + bool flush_relay_log_cache, + bool need_lock_relay_log) { IO_CACHE* file = &mi->file; char lbuf[22]; @@ -436,8 +438,19 @@ int flush_master_info(Master_info* mi, bool flush_relay_log_cache) */ if (flush_relay_log_cache) { + pthread_mutex_t *log_lock= mi->rli.relay_log.get_log_lock(); IO_CACHE *log_file= mi->rli.relay_log.get_log_file(); - if (flush_io_cache(log_file)) + + if (need_lock_relay_log) + pthread_mutex_lock(log_lock); + + safe_mutex_assert_owner(log_lock); + err= flush_io_cache(log_file); + + if (need_lock_relay_log) + pthread_mutex_unlock(log_lock); + + if (err) DBUG_RETURN(2); } |