本人完全不懂MySQL源碼,以下文字純屬瞎猜,如有誤導,概不負責!
在sql/rpl_slave.cc檔案中,time_diff的計算代碼為:
if (mi->rli->slave_running)
{
if ((mi->get_master_log_pos() == mi->rli->get_group_master_log_pos()) &&(!strcmp(mi->get_master_log_name(), mi->rli->get_group_master_log_name())))
{if (mi->slave_running ==MYSQL_SLAVE_RUN_CONNECT)
protocol->store(0LL);elseprotocol->store_null();
}else{long time_diff= ((long)(time(0) - mi->rli->last_master_timestamp)- mi->clock_diff_with_master);protocol->store((longlong)(mi->rli->last_master_timestamp ?max(0L, time_diff) : 0));
}
}else{
protocol->store_null();
}
1、當SQL線程停止時,傳回NULL
2、當SLAVE正常運作時,如果SQL線程執行的位置是relay log的最後位置則傳回0,否則傳回NULL
3、當SLAVE正常運作時,複制延遲時間=目前從庫系統時間(time(0)) - SQL線程處理的最後binlog的時間( mi->rli->last_master_timestamp) - 主從系統時間差(mi->clock_diff_with_master)
主從系統時間差(mi->clock_diff_with_master)
在sql/rpl_slave.cc檔案中,主從系統時間差計算代碼如下:
DBUG_EXECUTE_IF("dbug.before_get_UNIX_TIMESTAMP",
{const char act[]=
"now"
"wait_for signal.get_unix_timestamp";
DBUG_ASSERT(opt_debug_sync_timeout> 0);
DBUG_ASSERT(!debug_sync_set_action(current_thd,
STRING_WITH_LEN(act)));
};);
master_res=NULL;if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECT UNIX_TIMESTAMP()")) &&(master_res= mysql_store_result(mysql)) &&(master_row=mysql_fetch_row(master_res)))
{
mysql_mutex_lock(&mi->data_lock);
mi->clock_diff_with_master=(long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10));
mysql_mutex_unlock(&mi->data_lock);
}else if (check_io_slave_killed(mi->info_thd, mi, NULL))gotoslave_killed_err;else if(is_network_error(mysql_errno(mysql)))
{
mi->report(WARNING_LEVEL, mysql_errno(mysql),"Get master clock failed with error: %s", mysql_error(mysql));gotonetwork_err;
}else{
mysql_mutex_lock(&mi->data_lock);
mi->clock_diff_with_master= 0; mysql_mutex_unlock(&mi->data_lock);
sql_print_warning("\"SELECT UNIX_TIMESTAMP()\" failed on master,"
"do not trust column Seconds_Behind_Master of SHOW"
"SLAVE STATUS. Error: %s (%d)",
mysql_error(mysql), mysql_errno(mysql));
}if(master_res)
{
mysql_free_result(master_res);
master_res=NULL;
}
主從系統時間差=從庫目前時間(time((time_t*) 0)) - 主庫時間(UNIX_TIMESTAMP()),而主庫時間是到主庫上執行SELECT UNIX_TIMESTAMP(),然後取執行結果(strtoul(master_row[0], 0, 10))
SQL線程處理的最後binlog的時間( mi->rli->last_master_timestamp)
在sql/rpl_slave.cc檔案中exec_relay_log_event方法中,計算last_master_timestamp的代碼如下:
static int exec_relay_log_event(THD* thd, Relay_log_info*rli)
{
DBUG_ENTER("exec_relay_log_event");mysql_mutex_lock(&rli->data_lock);
if (rli->until_condition == Relay_log_info::UNTIL_SQL_AFTER_GTIDS &&rli->is_until_satisfied(thd, NULL))
{
rli->abort_slave= 1;
mysql_mutex_unlock(&rli->data_lock);
DBUG_RETURN(1);
}
Log_event*ev = next_event(rli), **ptr_ev;
DBUG_ASSERT(rli->info_thd==thd);if(sql_slave_killed(thd,rli))
{
mysql_mutex_unlock(&rli->data_lock);
delete ev;
DBUG_RETURN(1);
}if(ev)
{enumenum_slave_apply_event_and_update_pos_retval exec_res;
ptr_ev= &ev;
if (!(rli->is_parallel_exec() ||ev->is_artificial_event() || ev->is_relay_log_event() ||ev->when.tv_sec == 0 || ev->get_type_code() == FORMAT_DESCRIPTION_EVENT ||ev->server_id == 0))
{
rli->last_master_timestamp= ev->when.tv_sec + (time_t) ev->exec_time;
DBUG_ASSERT(rli->last_master_timestamp >= 0);
}
其中when.tv_sec是目前從庫時間,when.tv_sec的指派在sql/rpl_rli_pdb.cc檔案中slave_worker_exec_job方法中:
ev= static_cast(job_item->data);
thd->server_id = ev->server_id;
thd->set_time();
thd->lex->current_select= 0;if (!ev->when.tv_sec)
ev->when.tv_sec= my_time(0);
ev->thd= thd; //todo: assert because up to this point, ev->thd == 0
ev->worker= worker;
而my_time(0)傳回系統時間,代碼在mysys/my_getsystime.cc檔案
time_t my_time(myf flags)
{
time_t t;
while ((t= time(0)) == (time_t) -1)
{if (flags &MY_WME)
fprintf(stderr,"%s: Warning: time() call failed\n", my_progname);
}returnt;
}
而ev->exec_time的計算在sql/log_event.cc中的代碼如下:
structtimeval end_time;
ulonglong micro_end_time=my_micro_time();
my_micro_time_to_timeval(micro_end_time,&end_time);
exec_time= end_time.tv_sec - thd_arg->start_time.tv_sec;
exec_time在檔案sql/log_event.h中的注解如下:
exec_time4 byte unsigned integerThe time from when the query started to when it was logged inthe binlog,in seconds.
原文:https://www.cnblogs.com/gaogao67/p/11075648.html