天天看點

mysql replication延遲_MySQL Replication--複制延遲(Seconds_Behind_Master)計算01

本人完全不懂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