diff options
Diffstat (limited to 'sql/slave.cc')
-rw-r--r-- | sql/slave.cc | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/sql/slave.cc b/sql/slave.cc index 9ddbe7d05de..6b8559859fc 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -658,7 +658,7 @@ int terminate_slave_threads(MASTER_INFO* mi,int thread_mask,bool skip_lock) int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock, pthread_mutex_t *cond_lock, pthread_cond_t* term_cond, - volatile bool* slave_running) + volatile uint *slave_running) { if (term_lock) { @@ -696,7 +696,7 @@ int terminate_slave_thread(THD* thd, pthread_mutex_t* term_lock, int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock, pthread_mutex_t *cond_lock, pthread_cond_t *start_cond, - volatile bool *slave_running, + volatile uint *slave_running, volatile ulong *slave_run_id, MASTER_INFO* mi, bool high_priority) @@ -1081,7 +1081,7 @@ void end_slave() static bool io_slave_killed(THD* thd, MASTER_INFO* mi) { DBUG_ASSERT(mi->io_thd == thd); - DBUG_ASSERT(mi->slave_running == 1); // tracking buffer overrun + DBUG_ASSERT(mi->slave_running); // tracking buffer overrun return mi->abort_slave || abort_loop || thd->killed; } @@ -1949,19 +1949,13 @@ void init_master_info_with_options(MASTER_INFO* mi) strmake(mi->ssl_key, master_ssl_key, sizeof(mi->ssl_key)-1); } -static void clear_slave_error(RELAY_LOG_INFO* rli) +void clear_slave_error(RELAY_LOG_INFO* rli) { /* Clear the errors displayed by SHOW SLAVE STATUS */ rli->last_slave_error[0]= 0; rli->last_slave_errno= 0; } -void clear_slave_error_timestamp(RELAY_LOG_INFO* rli) -{ - rli->last_master_timestamp= 0; - clear_slave_error(rli); -} - /* Reset UNTIL condition for RELAY_LOG_INFO SYNOPSYS @@ -2349,6 +2343,11 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) String *packet= &thd->packet; protocol->prepare_for_resend(); + /* + TODO: we read slave_running without run_lock, whereas these variables + are updated under run_lock and not data_lock. In 5.0 we should lock + run_lock on top of data_lock (with good order). + */ pthread_mutex_lock(&mi->data_lock); pthread_mutex_lock(&mi->rli.data_lock); @@ -2409,7 +2408,12 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) protocol->store(mi->ssl_cipher, &my_charset_bin); protocol->store(mi->ssl_key, &my_charset_bin); - if (mi->rli.last_master_timestamp) + /* + Seconds_Behind_Master: if SQL thread is running and I/O thread is + connected, we can compute it otherwise show NULL (i.e. unknown). + */ + if ((mi->slave_running == MYSQL_SLAVE_RUN_CONNECT) && + mi->rli.slave_running) { long tmp= (long)((time_t)time((time_t*) 0) - mi->rli.last_master_timestamp) @@ -2429,9 +2433,13 @@ bool show_master_info(THD* thd, MASTER_INFO* mi) slave is 2. At SHOW SLAVE STATUS time, assume that the difference between timestamp of slave and rli->last_master_timestamp is 0 (i.e. they are in the same second), then we get 0-(2-1)=-1 as a result. - This confuses users, so we don't go below 0. + This confuses users, so we don't go below 0: hence the max(). + + last_master_timestamp == 0 (an "impossible" timestamp 1970) is a + special marker to say "consider we have caught up". */ - protocol->store((longlong)(max(0, tmp))); + protocol->store((longlong)(mi->rli.last_master_timestamp ? max(0, tmp) + : 0)); } else protocol->store_null(); @@ -3280,6 +3288,8 @@ slave_begin: connected: + // TODO: the assignment below should be under mutex (5.0) + mi->slave_running= MYSQL_SLAVE_RUN_CONNECT; thd->slave_net = &mysql->net; thd->proc_info = "Checking master version"; if (get_master_version_and_clock(mysql, mi)) @@ -3312,6 +3322,7 @@ dump"); goto err; } + mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT; thd->proc_info= "Waiting to reconnect after a failed binlog dump request"; #ifdef SIGNAL_WITH_VIO_CLOSE thd->clear_active_vio(); @@ -3388,6 +3399,7 @@ max_allowed_packet", mysql_error(mysql)); goto err; } + mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT; thd->proc_info = "Waiting to reconnect after a failed master event read"; #ifdef SIGNAL_WITH_VIO_CLOSE thd->clear_active_vio(); @@ -3566,6 +3578,14 @@ slave_begin: pthread_mutex_lock(&LOCK_thread_count); threads.append(thd); pthread_mutex_unlock(&LOCK_thread_count); + /* + We are going to set slave_running to 1. Assuming slave I/O thread is + alive and connected, this is going to make Seconds_Behind_Master be 0 + i.e. "caught up". Even if we're just at start of thread. Well it's ok, at + the moment we start we can think we are caught up, and the next second we + start receiving data so we realize we are not caught up and + Seconds_Behind_Master grows. No big deal. + */ rli->slave_running = 1; rli->abort_slave = 0; pthread_mutex_unlock(&rli->run_lock); @@ -4604,6 +4624,21 @@ Log_event* next_event(RELAY_LOG_INFO* rli) */ if (hot_log) { + /* + We say in Seconds_Behind_Master that we have "caught up". Note that + for example if network link is broken but I/O slave thread hasn't + noticed it (slave_net_timeout not elapsed), then we'll say "caught + up" whereas we're not really caught up. Fixing that would require + internally cutting timeout in smaller pieces in network read, no + thanks. Another example: SQL has caught up on I/O, now I/O has read + a new event and is queuing it; the false "0" will exist until SQL + finishes executing the new event; it will be look abnormal only if + the events have old timestamps (then you get "many", 0, "many"). + Transient phases like this can't really be fixed. + */ + time_t save_timestamp= rli->last_master_timestamp; + rli->last_master_timestamp= 0; + DBUG_ASSERT(rli->relay_log.get_open_count() == rli->cur_log_old_open_count); /* We can, and should release data_lock while we are waiting for @@ -4650,6 +4685,7 @@ Log_event* next_event(RELAY_LOG_INFO* rli) rli->relay_log.wait_for_update(rli->sql_thd, 1); // re-acquire data lock since we released it earlier pthread_mutex_lock(&rli->data_lock); + rli->last_master_timestamp= save_timestamp; continue; } /* |