Seconds_Behind_Master
對於mysql主備實例,seconds_behind_master是衡量master與slave之間延時的一個重要參數。通過在slave上執行"show slave status;"可以獲取seconds_behind_master的值。
原始實現
Definition:The number of seconds that the slave SQL thread is behind processing the master binary log.
Type:time_t(long)
計算方式如下:
rpl_slave.cc::show_slave_status_send_data()
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);
else
protocol->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));
}
主要分爲以下兩種情況:
• SQL線程等待IO線程獲取主機binlog,此時seconds_behind_master爲0,表示備機與主機之間無延時;
• SQL線程處理relay log,此時seconds_behind_master通過(long)(time(0) – mi->rli->last_master_timestamp) – mi->clock_diff_with_master計算得到;
last_master_timestamp
定義:
• 主庫binlog中事件的時間。
• type: time_t (long)
計算方式:
last_master_timestamp根據備機是否並行複製有不同的計算方式。
非並行複製:
rpl_slave.cc:exec_relay_log_event()
if ((!rli->is_parallel_exec() || rli->last_master_timestamp == 0) &&
!(ev->is_artificial_event() || ev->is_relay_log_event() ||
(ev->common_header->when.tv_sec == 0) ||
ev->get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT ||
ev->server_id == 0))
{
rli->last_master_timestamp= ev->common_header->when.tv_sec +
(time_t) ev->exec_time;
DBUG_ASSERT(rli->last_master_timestamp >= 0);
}
在該模式下,last_master_timestamp表示爲每一個event的結束時間,其中when.tv_sec表示event的開始時間,exec_time表示事務的執行時間。該值的計算在apply_event之前,所以event還未執行時,last_master_timestamp已經被更新。由於exec_time僅在Query_log_event中存在,所以last_master_timestamp在應用一個事務的不同event階段變化。以一個包含兩條insert語句的事務爲例,在該代碼段的調用時,打印出event的類型、時間戳和執行時間
create table t1(a int PRIMARY KEY AUTO_INCREMENT ,b longblob) engine=innodb;
begin;
insert into t1(b) select repeat('a',104857600);
insert into t1(b) select repeat('a',104857600);
commit;
2020-02-10T06:41:32.628554Z 11 [Note] [MY-000000] [Repl] event_type: 33 GTID_LOG_EVENT
2020-02-10T06:41:32.628601Z 11 [Note] [MY-000000] [Repl] event_time: 1581316890
2020-02-10T06:41:32.628614Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0
2020-02-10T06:41:32.628692Z 11 [Note] [MY-000000] [Repl] event_type: 2 QUERY_EVENT
2020-02-10T06:41:32.628704Z 11 [Note] [MY-000000] [Repl] event_time: 1581316823
2020-02-10T06:41:32.628713Z 11 [Note] [MY-000000] [Repl] event_exec_time: 35
2020-02-10T06:41:32.629037Z 11 [Note] [MY-000000] [Repl] event_type: 19 TABLE_MAP_EVENT
2020-02-10T06:41:32.629057Z 11 [Note] [MY-000000] [Repl] event_time: 1581316823
2020-02-10T06:41:32.629063Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0
2020-02-10T06:41:33.644111Z 11 [Note] [MY-000000] [Repl] event_type: 30 WRITE_ROWS_EVENT
2020-02-10T06:41:33.644149Z 11 [Note] [MY-000000] [Repl] event_time: 1581316823
2020-02-10T06:41:33.644156Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0
2020-02-10T06:41:43.520272Z 0 [Note] [MY-011953] [InnoDB] Page cleaner took 9185ms to flush 3 and evict 0 pages
2020-02-10T06:42:05.982458Z 11 [Note] [MY-000000] [Repl] event_type: 19 TABLE_MAP_EVENT
2020-02-10T06:42:05.982488Z 11 [Note] [MY-000000] [Repl] event_time: 1581316858
2020-02-10T06:42:05.982495Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0
2020-02-10T06:42:06.569345Z 11 [Note] [MY-000000] [Repl] event_type: 30 WRITE_ROWS_EVENT
2020-02-10T06:42:06.569376Z 11 [Note] [MY-000000] [Repl] event_time: 1581316858
2020-02-10T06:42:06.569384Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0
2020-02-10T06:42:16.506176Z 0 [Note] [MY-011953] [InnoDB] Page cleaner took 9352ms to flush 8 and evict 0 pages
2020-02-10T06:42:37.202507Z 11 [Note] [MY-000000] [Repl] event_type: 16 XID_EVENT
2020-02-10T06:42:37.202539Z 11 [Note] [MY-000000] [Repl] event_time: 1581316890
2020-02-10T06:42:37.202546Z 11 [Note] [MY-000000] [Repl] event_exec_time: 0
並行複製:
rpl_slave.cc mts_checkpoint_routine
ts = rli->gaq->empty()
? 0
: reinterpret_cast<Slave_job_group *>(rli->gaq->head_queue())->ts;
rli->reset_notified_checkpoint(cnt, ts, true);
/* end-of "Coordinator::"commit_positions" */
在該模式下備機上存在一個分發隊列gaq,如果gaq爲空,則設置last_commit_timestamp爲0;如果gaq不爲空,則此時維護一個checkpoint點lwm,lwm之前的事務全部在備機上執行完成,此時last_commit_timestamp被更新爲lwm所在事務執行完成後的時間。該時間類型爲time_t類型。
ptr_group->ts = common_header->when.tv_sec +
(time_t)exec_time; // Seconds_behind_master related
rli->rli_checkpoint_seqno++;
if (update_timestamp) {
mysql_mutex_lock(&data_lock);
last_master_timestamp = new_ts;
mysql_mutex_unlock(&data_lock);
}
在並行複製下,event執行完成之後纔會更新last_master_timestamp,所以非並行複製和並行複製下的seconds_behind_master會存在差異。
clock_diff_with_master
定義:
• The difference in seconds between the clock of the master and the clock of the slave (second - first). It must be signed as it may be <0 or >0. clock_diff_with_master is computed when the I/O thread starts; for this the I/O thread does a SELECT UNIX_TIMESTAMP() on the master.
• type: long
rpl_slave.cc::get_master_version_and_clock()
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));
DBUG_EXECUTE_IF("dbug.mts.force_clock_diff_eq_0",
mi->clock_diff_with_master= 0;);
mysql_mutex_unlock(&mi->data_lock);
}
該差值僅被計算一次,在master與slave建立聯繫時處理。
其他
exec_time
定義:
• the difference from the statement’s original start timestamp and the time at which it completed executing.
• type: unsigned long
struct timeval 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->query_start_in_secs();
時間函數
(1)time_t time(time_t timer) time_t爲long類型,返回的數值僅精確到秒;
(2)int gettimeofday (struct timeval *tv, struct timezone *tz) 可以獲得微秒級的當前時間;
(3)timeval結構
#include <time.h>
stuct timeval {
time_t tv_sec; /*seconds*/
suseconds_t tv_usec; /*microseconds*/
}
總結
使用seconds_behind_master衡量主備延時只能精確到秒級別,且在某些場景下,seconds_behind_master並不能準確反映主備之間的延時。主備異常時,可以結合seconds_behind_master源碼進行具體分析。
點擊這裏,瞭解更多精彩內容