日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

mysql seconds_behind_master_MySQL 复制延迟 Seconds_Behind_Master 究竟是如何计算的

發(fā)布時(shí)間:2025/6/15 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql seconds_behind_master_MySQL 复制延迟 Seconds_Behind_Master 究竟是如何计算的 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原標(biāo)題:MySQL 復(fù)制延遲 Seconds_Behind_Master 究竟是如何計(jì)算的

導(dǎo)讀:

作者:羅小波

參考鏈接

https://dev.mysql.com/doc/refman/5.7/en/show-slave-status.html

https://wemp.app/posts/33881a28-ba27-4908-994e-29440455d5be https://blog.csdn.net/innobase/article/details/51302138

歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處!

目錄

"口口相傳" 的計(jì)算方法

探尋 "正確" 的計(jì)算方法

驗(yàn)證 我們想確認(rèn)什么 提前確認(rèn)一些信息 執(zhí)行驗(yàn)證

總結(jié)

背景說(shuō)明

在使用主從復(fù)制的拓?fù)渲?#xff0c;監(jiān)控復(fù)制延遲時(shí)間是必不可少的功課,如果應(yīng)用場(chǎng)景對(duì)復(fù)制延遲并不敏感,那么,大多數(shù)時(shí)候通過(guò)采集 SHOW SLAVE STATUS 語(yǔ)句輸出信息中的 Seconds_Behind_Master 字段值來(lái)監(jiān)控復(fù)制延遲就已經(jīng)足夠了,相信有MySQL使用經(jīng)驗(yàn)的人對(duì)通過(guò)這種方法來(lái)查看復(fù)制延遲并不陌生,我們都知道 Seconds_Behind_Master 的值在某些場(chǎng)景下并不是那么可靠,也或多或少都知道一些 Seconds_Behind_Master 字段值計(jì)算方法。但這些計(jì)算方法真的正確么?

本著鉆研的精神,今天我就較真一回,搜羅一些關(guān)于計(jì)算方法的傳說(shuō),并進(jìn)行一些簡(jiǎn)單的驗(yàn)證,整理出來(lái),洋洋灑灑寫(xiě)了一大篇,在這里分享給大家

一、"口口相傳" 的計(jì)算方法

?方法一:從庫(kù) I/O 線程讀取的主庫(kù) binlog event 時(shí)間戳與 SQL 線程正在執(zhí)行的 binlog event 的時(shí)間戳之間的時(shí)間差,單位為秒

該方法其實(shí)就是在計(jì)算兩個(gè)線程處理日志的時(shí)間差,這也是目前最為 "流行" 的一種說(shuō)法。基于這個(gè)算法,如果主從之間的網(wǎng)絡(luò)存在很大延遲的時(shí)候,主庫(kù)中就可能存在著大量的binlog還沒(méi)來(lái)得及發(fā)送給從庫(kù),那么這個(gè)時(shí)候其實(shí)使用該方法計(jì)算出來(lái)的延遲時(shí)間,跟主從之間數(shù)據(jù)真正的延遲就沒(méi)有太大關(guān)系了

?方法二:從庫(kù)的系統(tǒng)(主機(jī))時(shí)間與 I/O 線程讀取的主庫(kù) binlog event 的時(shí)間差之間的時(shí)間差,單位為秒

這種說(shuō)法沒(méi)那么 "流行" ,基于這個(gè)算法,如果從庫(kù)的操作系統(tǒng)時(shí)間被更改了,或者主庫(kù)的操作系統(tǒng)時(shí)間被修改了,即主從庫(kù)的主機(jī)時(shí)間差本身就比較大的時(shí)候,那么計(jì)算出來(lái)的結(jié)果也毫無(wú)參考意義

? 結(jié)論,看起來(lái)這兩種算法都不太靠譜,正確的算法真的是這樣的嗎?為了一探究竟,我們需要找到可靠的信息源進(jìn)行確認(rèn)。

那么從哪里可以獲得可靠的信息源呢?

二、探尋 "正確" 的計(jì)算方法

?信息源一:MySQL 官方手冊(cè)

為了不占篇幅、也為了避免本人英文理解錯(cuò)誤,下面直接貼出官方手冊(cè)中關(guān)于 Seconds_Behind_Master 字段值計(jì)算描述的原文

大概的含義:

* 當(dāng)從庫(kù)正在不斷地處理更新時(shí)(持續(xù)不斷有event被SQL線程或者I/O線程處理時(shí)),此字段顯示從庫(kù)主機(jī)當(dāng)前時(shí)間戳和來(lái)自主庫(kù)(原始)的二進(jìn)制日志中記錄的時(shí)間戳之間的差異

* 當(dāng)從庫(kù)沒(méi)有任何需要處理的更新時(shí),如果I/O和SQL線程狀態(tài)都為Yes,則此字段顯示為0,如果有任意一個(gè)線程狀態(tài)不為Yes,則此字段顯示為NULL

* 實(shí)際上,這個(gè)字段是度量從庫(kù)SQL線程和I/O線程之間的時(shí)間差,單位為秒,如果主備之間的網(wǎng)絡(luò)非常快,那么從庫(kù)的I/O線程讀取的主庫(kù)binlog會(huì)與主庫(kù)中最新的binlog非常接近,所以這樣計(jì)算得來(lái)得值就可以作為主備之間的數(shù)據(jù)延遲時(shí)間,但是如果主備之間的網(wǎng)絡(luò)非常慢,可能導(dǎo)致從庫(kù)SQL線程正在重放的主庫(kù)binlog 非常接近從庫(kù)I/O線程讀取的主庫(kù)binlog,而I/O線程因?yàn)榫W(wǎng)絡(luò)慢的原因可能讀取的主庫(kù)binlog遠(yuǎn)遠(yuǎn)落后于主庫(kù)最新的binlog,此時(shí),這么計(jì)算得來(lái)的值是不可靠的,盡管這個(gè)時(shí)候有可能該字段顯示為0,但實(shí)際上可能從庫(kù)已經(jīng)落后于主庫(kù)非常多了。所以,對(duì)于網(wǎng)絡(luò)比較慢的情況,該值并不可靠

* 如果主庫(kù)與從庫(kù)的server自身的時(shí)間不一致,那么,只要從庫(kù)復(fù)制線程啟動(dòng)之后,沒(méi)有做過(guò)任何時(shí)間變更,那么這個(gè)字段的值也可以正常計(jì)算,但是如果修改了server的時(shí)間,則可能導(dǎo)致時(shí)鐘偏移,從而導(dǎo)致這個(gè)計(jì)算值不可靠

* 如果從庫(kù)的SQL線程沒(méi)運(yùn)行、SQL線程正在運(yùn)行且已經(jīng)消費(fèi)完了所有的relay log且I/O線程沒(méi)有運(yùn)行,則該字段顯示為NULL(如果I/O線程已經(jīng)停止,但還存在著relay log未重放完成時(shí),仍然會(huì)顯示出復(fù)制延遲時(shí)間,直到所有relay log被重放完成之后,顯示為NULL),如果SQL線程和I/O線程都運(yùn)行著,但是處于空閑狀態(tài)(SQL線程已經(jīng)重放完了I/O線程產(chǎn)生的

relay log),則該字段顯示為0

* 該字段的值是基于存儲(chǔ)在主庫(kù)binlog event中的時(shí)間戳,保留這個(gè)時(shí)間戳并通過(guò)復(fù)制架構(gòu)同步到從庫(kù)進(jìn)行計(jì)算得來(lái),那就意味著正常的復(fù)制情況下(排除人為在從庫(kù)寫(xiě)入數(shù)據(jù)的情況)主庫(kù)與從庫(kù)上的binlog event的時(shí)間戳都來(lái)自主庫(kù),在目前的計(jì)算該字段值的算法中有一個(gè)問(wèn)題,在單線程復(fù)制場(chǎng)景下,即如果從庫(kù)上通過(guò)客戶端連接進(jìn)入并直接更新數(shù)據(jù),這可能導(dǎo)致該字段的值隨機(jī)波動(dòng),因?yàn)橛袝r(shí)候event來(lái)源于主庫(kù),有時(shí)候來(lái)源于從庫(kù)直接更新產(chǎn)生的event,而這個(gè)字段的值會(huì)受到直接更新產(chǎn)生的event的影響。但如果是多線程復(fù)制,則此值是基于Exec_Master_Log_Pos點(diǎn)的event時(shí)間戳來(lái)計(jì)算的,因此可能不會(huì)反映從庫(kù)最近提交的事務(wù)的位置

?信息源二:源碼

以下是源碼中關(guān)于延遲時(shí)間計(jì)算方法的注釋說(shuō)明

# 位于rpl_mi.h中定義clock_diff_with_master附近(翻閱了5.6.34和5.7.22 兩個(gè)版本,對(duì)于復(fù)制延遲的計(jì)算公式兩者一致)

# 從源碼注釋上來(lái)看,復(fù)制延遲的計(jì)算公式為 clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master

# 該公式的含義為:從庫(kù)的當(dāng)前系統(tǒng)(主機(jī))時(shí)間 - 從庫(kù) SQL 線程正在執(zhí)行的event的時(shí)間戳 - 主從庫(kù)的系統(tǒng)(主機(jī))之間的時(shí)間差

/*

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.

"how late the slave is compared to the master" is computed like this:

clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master

*/

# clock_diff_with_master 值為主從服務(wù)器的主機(jī)時(shí)間差,該值只在I/O線程啟動(dòng)時(shí)計(jì)算一次,后續(xù)每次計(jì)算Seconds_Behind_Master字段值時(shí),是直接復(fù)用這個(gè)計(jì)算結(jié)果,每次重啟I/O線程時(shí)該值會(huì)重新計(jì)算

long clock_diff_with_master;

# master_row[0] 為從庫(kù)在主庫(kù)上執(zhí)行SELECT UNIX_TIMESTAMP()的操作,clock_diff_with_master為主從庫(kù)主機(jī)的時(shí)間差計(jì)算結(jié)果

mi->clock_diff_with_master=

(long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10));

# 從rpl_slave.cc 文件中啟動(dòng) I/O 線程時(shí)可以看出:

start_slave_thread-> # 啟動(dòng)start slave

handle_slave_io-> # 啟動(dòng)start io thread

get_master_version_and_clock # 獲取當(dāng)前slave和主機(jī)之間的時(shí)間差(clock_diff_with_master)

以下是源碼中關(guān)于Seconds_Behind_Master 計(jì)算結(jié)果的一些判定值

/*

The pseudo code to compute Seconds_Behind_Master: # 闡明這是一段注釋關(guān)于如何計(jì)算Seconds_Behind_Master的偽代碼

if (SQL thread is running) # 如果SQL線程正在運(yùn)行,則進(jìn)入這個(gè)if判斷內(nèi),假設(shè)這里標(biāo)記為if one

{

if (SQL thread processed all the available relay log) # 如果SQL線程應(yīng)用完成了所有可用的relay log,則進(jìn)入這個(gè)if判斷內(nèi),假設(shè)這里標(biāo)記為if two

{

if (IO thread is running) # 如果I/O線程正在運(yùn)行,則進(jìn)入這個(gè)if判斷內(nèi),假設(shè)這里標(biāo)記為if three

print 0; # 如果if one/two/three三個(gè)條件都為真,則延遲值判定為0

else

print NULL; # 如果if one/two為真,if three為假,則延遲值判定為NULL

}

else

compute Seconds_Behind_Master; # 如果if one為真,if two為假,則執(zhí)行公式計(jì)算延遲值

}

else

print NULL; # 如果if one為假,則延遲值判定為NULL

*/

if (mi->rli->slave_running)

{

/*

Check if SQL thread is at the end of relay log

Checking should be done using two conditions

condition1: compare the log positions and

condition2: compare the file names (to handle rotation case)

*/

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);

/*

Apparently on some systems time_diff can be <0. Here are possible

reasons related to MySQL:

- the master is itself a slave of another master whose time is ahead.

- somebody used an explicit SET TIMESTAMP on the master.

Possible reason related to granularity-to-second of time functions

(nothing to do with MySQL), which can explain a value of -1:

assume the master's and slave's time are perfectly synchronized, and

that at slave's connection time, when the master's timestamp is read,

it is at the very end of second 1, and (a very short time later) when

the slave's timestamp is read it is at the very beginning of second

2. Then the recorded value for master is 1 and the recorded value for

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: 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)(mi->rli->last_master_timestamp ?

max(0L, time_diff) : 0)); # time_diff這里其實(shí)就是最終計(jì)算的Seconds_Behind_Master 值,如果為負(fù)數(shù),則直接歸零

}

}

三、驗(yàn)證

1、我們想確認(rèn)什么

正所謂 "盡信書(shū)不如無(wú)書(shū)" ,我們不能 "它說(shuō)是這樣我們就信了" ,所以,我們這里簡(jiǎn)單對(duì)官方手冊(cè)和源碼中提及的計(jì)算公式、場(chǎng)景進(jìn)行簡(jiǎn)單的驗(yàn)證,看看實(shí)際的表現(xiàn)如何

根據(jù)上文源碼中的注釋,我們找到了計(jì)算復(fù)制延遲的 "正確" 方法(公式)為: * clock_of_slave - last_timestamp_executed_by_SQL_thread - clock_diff_with_master,該公式含義為 "從庫(kù)的當(dāng)前系統(tǒng)(主機(jī))時(shí)間 - 從庫(kù) SQL 線程正在執(zhí)行的event的時(shí)間戳 - 主從庫(kù)的系統(tǒng)(主機(jī))之間的時(shí)間差" * 計(jì)算公式中的clock_diff_with_master值,也就是主從庫(kù)的主機(jī)時(shí)差只在I/O線程啟動(dòng)的時(shí)候計(jì)算一次(后續(xù)會(huì)復(fù)用該計(jì)算結(jié)果來(lái)計(jì)算復(fù)制延遲,直到下次重啟I/O線程時(shí)才會(huì)重新計(jì)算)

根據(jù)上文官方手冊(cè)中的描述,主從庫(kù)系統(tǒng)時(shí)間不一致也支持正確計(jì)算復(fù)制延遲: * 如果主從庫(kù)的系統(tǒng)時(shí)間不一致,那么如果在復(fù)制線程(I/O線程)啟動(dòng)之后,沒(méi)有對(duì)主庫(kù)或者從庫(kù)的系統(tǒng)時(shí)間再次進(jìn)行修改,那么根據(jù)公式是可以正確計(jì)算復(fù)制延遲時(shí)間的,除非在復(fù)制啟動(dòng)之后再次修改了主從庫(kù)的系統(tǒng)時(shí)間,就會(huì)導(dǎo)致復(fù)制延遲時(shí)間不可靠(因?yàn)橛?jì)算公式中的clock_diff_with_master 只在I/O線程啟動(dòng)時(shí)才會(huì)進(jìn)行計(jì)算,后續(xù)計(jì)算復(fù)制延遲時(shí)會(huì)復(fù)用該計(jì)算結(jié)果)

根據(jù)上文源碼中的描述,當(dāng)Seconds_Behind_Master計(jì)算結(jié)果為負(fù)數(shù)的時(shí)候,直接歸零

2、提前確認(rèn)一些信息

首先:我們需要確認(rèn)當(dāng)I/O線程啟動(dòng)之后,會(huì)在主庫(kù)上執(zhí)行一些什么動(dòng)作?

然后:我們需要確認(rèn)直接修改主機(jī)時(shí)間之后,在數(shù)據(jù)庫(kù)中執(zhí)行一些時(shí)間函數(shù)是返回的時(shí)間信息是否會(huì)跟著改變,寫(xiě)入到二進(jìn)制日志中的時(shí)間信息是否會(huì)跟著改變?

我們先來(lái)看第一個(gè)問(wèn)題,當(dāng)I/O線程啟動(dòng)之后,會(huì)在主庫(kù)上執(zhí)行一些什么動(dòng)作?

先在主庫(kù)打開(kāi)general_log

root@localhost : (none) 10:09:47> set globalgeneral_log=1;

Query OK, 0 rows affected (0.01 sec)

從庫(kù)啟動(dòng) I/O 線程

root@localhost : (none) 10:16:33> start slave io_thread;

Query OK, 0 rows affected (0.00 sec)

查看主庫(kù)general_log中記錄的內(nèi)容

2019-04-18T10:16:36.414222+08:00 8 Connect qbench@10.10.30.162 on using TCP/IP

2019-04-18T10:16:36.414632+08:00 8 Query SELECT UNIX_TIMESTAMP() # 在主庫(kù)查詢系統(tǒng)時(shí)間語(yǔ)句,這里可以證實(shí)I/O線程啟動(dòng)的時(shí)候會(huì)獲取主庫(kù)的系統(tǒng)時(shí)間,當(dāng)從庫(kù)拿到主庫(kù)的系統(tǒng)時(shí)間之后,就可以計(jì)算主從庫(kù)的系統(tǒng)時(shí)間之差

2019-04-18T10:16:36.415401+08:00 8 Query SELECT @@GLOBAL.SERVER_ID # 查詢主庫(kù)的SERVER_ID

2019-04-18T10:16:36.415638+08:00 8 Query SET @master_heartbeat_period= 5000000000 # 對(duì)dump線程在會(huì)話級(jí)別設(shè)置心跳間隔時(shí)間

2019-04-18T10:16:36.415814+08:00 8 Query SET @master_binlog_checksum= @@global.binlog_checksum

2019-04-18T10:16:36.416129+08:00 8 Query SELECT @master_binlog_checksum

2019-04-18T10:16:36.416335+08:00 8 Query SELECT @@GLOBAL.GTID_MODE # 查詢主庫(kù)的GTID模式值

2019-04-18T10:16:36.416527+08:00 8 Query SELECT @@GLOBAL.SERVER_UUID # 查詢主庫(kù)的UUID

2019-04-18T10:16:36.416693+08:00 8 Query SET @slave_uuid= '2d623f55-2111-11e8-9cc3-0025905b06da' # 會(huì)話級(jí)別設(shè)置從庫(kù)自己的UUID

2019-04-18T10:16:36.417224+08:00 8 Binlog Dump GTID Log: '' Pos: 4 GTIDs: '06188301-b333-11e8-bdfe-0025905b06da:1-270852,

2d623f55-2111-11e8-9cc3-0025905b06da:1,

f3372787-0719-11e8-af1f-0025905b06da:1-21'

現(xiàn)在,我們來(lái)看第二個(gè)問(wèn)題。修改主機(jī)時(shí)間之后(數(shù)據(jù)庫(kù)進(jìn)程不重啟),在數(shù)據(jù)庫(kù)中執(zhí)行一些時(shí)間函數(shù)時(shí)返回的時(shí)間信息是否會(huì)跟著改變,寫(xiě)入到二進(jìn)制日志中的時(shí)間信息是否會(huì)跟著改變

在主庫(kù)的主機(jī)中修改時(shí)間

# 修改之前先查詢一下主機(jī)和數(shù)據(jù)庫(kù)中的時(shí)間,都為2019-04-19 16:14附近

[root@localhost ~]# date

2019年 04月 19日 星期五 16:14:19 CST

# 修改之前先查看數(shù)據(jù)庫(kù)中的時(shí)間

mysql > select now(),unix_timestamp(),from_unixtime(unix_timestamp());

+---------------------+------------------+---------------------------------+

| now() | unix_timestamp() | from_unixtime(unix_timestamp()) |

+---------------------+------------------+---------------------------------+

| 2019-04-19 16:14:20 | 1555661660 | 2019-04-19 16:14:20 |

+---------------------+------------------+---------------------------------+

# 修改主機(jī)時(shí)間為2020-04-19 17:15:00

[root@localhost ~]# date -s '2020-04-19 17:15:00'

2020年 04月 19日 星期日 17:15:00 CST

# 發(fā)現(xiàn)在數(shù)據(jù)庫(kù)中使用unix_timestamp()函數(shù)查詢到的時(shí)間跟隨著主機(jī)時(shí)間變化了,也變?yōu)榱?020-04-19

mysql > select now(),unix_timestamp(),from_unixtime(unix_timestamp());

+---------------------+------------------+---------------------------------+

| now() | unix_timestamp() | from_unixtime(unix_timestamp()) |

+---------------------+------------------+---------------------------------+

| 2020-04-19 17:15:03 | 1587287703 | 2020-04-19 17:15:03 |

+---------------------+------------------+---------------------------------+

# 插入一點(diǎn)測(cè)試數(shù)據(jù),解析binlog,發(fā)現(xiàn)binlog中的時(shí)間戳也跟著發(fā)生了變化,也變?yōu)榱?020-04-19 ,這里就可以證實(shí)主機(jī)時(shí)間的修改將直接影響數(shù)據(jù)庫(kù)中時(shí)間函數(shù)獲取的時(shí)間以及binlog的時(shí)間戳

......

# at 468

#190419 16:14:29 server id 3306154 end_log_pos 499 CRC32 0x80c44c50 Xid = 74

COMMIT/*!*/;

# at 499

#200419 17:15:08 server id 3306154 end_log_pos 564 CRC32 0xc2794ccb GTID last_committed=1 sequence_number=2 rbr_only=yes

/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;

SET @@SESSION.GTID_NEXT= 'c413c893-56b0-11e9-a705-000c29c10fa5:35'/*!*/;

......

3、執(zhí)行驗(yàn)證

驗(yàn)證場(chǎng)景

1、在主庫(kù)持續(xù)每秒有數(shù)據(jù)寫(xiě)入的情況下(腳本持續(xù)的每隔一秒插入10行數(shù)據(jù))驗(yàn)證主庫(kù)和從庫(kù)各自向前和向后修改主機(jī)時(shí)間、主從庫(kù)同時(shí)向前和向后修改主機(jī)時(shí)間時(shí),從庫(kù)的復(fù)制延遲時(shí)間如何變化(腳本持續(xù)每秒鐘獲取一次Seconds_Behind_Master字段值)

2、sysbench 加壓到從庫(kù)存在復(fù)制延遲的情況下,突然停止主庫(kù)壓力或突然停止從庫(kù) I/O線程時(shí),從庫(kù)復(fù)制延遲時(shí)間如何變化

驗(yàn)證結(jié)果

4、總結(jié)

根據(jù)以上可靠的信息來(lái)源以及測(cè)試驗(yàn)證過(guò)程可以簡(jiǎn)單得出如下一些結(jié)論

對(duì)于主從庫(kù)主機(jī)時(shí)間不一致的情況,在I/O線程第一次啟動(dòng)時(shí),會(huì)計(jì)算主從之間的主機(jī)時(shí)間差,在后續(xù)計(jì)算復(fù)制延遲時(shí),會(huì)把這個(gè)時(shí)間差減掉,這樣就可以保證正確獲取到復(fù)制延遲時(shí)間,但是該時(shí)間差只在I/O線程啟動(dòng)時(shí)才會(huì)進(jìn)行計(jì)算,所以,當(dāng)I/O線程啟動(dòng)之后修改了主從庫(kù)的主機(jī)時(shí)間,則根據(jù)計(jì)算公式,會(huì)導(dǎo)致復(fù)制延遲時(shí)間不可靠,但是當(dāng)I/O線程重啟之后就可以恢復(fù)(因?yàn)镮/O線程重啟時(shí),主從之間的時(shí)間差重新計(jì)算了)

在計(jì)算復(fù)制延遲時(shí)(執(zhí)行 SHOW SLAVE STATUS語(yǔ)句時(shí)會(huì)進(jìn)行計(jì)算),對(duì)Seconds_Behind_Master計(jì)算結(jié)果做一些判定(上文源碼介紹部分的偽代碼注釋里有講解過(guò),這里再啰嗦一下): * 如果 I/O 和 SQL線程同時(shí)為 Yes,且SQL線程沒(méi)有做任何事情(沒(méi)有需要被執(zhí)行的event),此時(shí)直接判定復(fù)制延遲結(jié)果為0,不會(huì)走公式計(jì)算延遲時(shí)間,否則會(huì)走公式計(jì)算延遲時(shí)間(所以,在該前置條件下不會(huì)出現(xiàn)當(dāng)主庫(kù)沒(méi)有寫(xiě)任何binlog event時(shí),從庫(kù)延遲不斷加大的情況) * 如果 SQL線程為Yes,且還存在著 I/O 線程已經(jīng)讀取的relay log未應(yīng)用完成的,則會(huì)走公式計(jì)算延遲時(shí)間,而不管 I/O線程是否正在運(yùn)行,但當(dāng)SQL線程重放完成了所有relay log時(shí),如果 I/O線程不為Yes,直接判定復(fù)制延遲結(jié)果為NULL * 任何時(shí)候,如果SQL線程不為Yes,直接判定復(fù)制延遲結(jié)果為NULL。當(dāng)計(jì)算出的復(fù)制延遲為負(fù)數(shù)時(shí),直接歸零

補(bǔ)充說(shuō)明:

1、當(dāng)SQL線程重放大事務(wù)時(shí),SQL線程的時(shí)間戳更新相當(dāng)于被暫停了(因?yàn)橐粋€(gè)大事務(wù)的event在重放時(shí)需要很長(zhǎng)時(shí)間才能完成,雖然這個(gè)大事務(wù)也可能會(huì)有很多event,但是這些event的時(shí)間戳可能全都相同),此時(shí),根據(jù)計(jì)算公式可以得出,無(wú)論主庫(kù)是否有新的數(shù)據(jù)寫(xiě)入,從庫(kù)復(fù)制延遲仍然會(huì)持續(xù)增大(也就是說(shuō)此時(shí)的復(fù)制延遲值是不可靠的)。所以就會(huì)出現(xiàn)主庫(kù)停止寫(xiě)入之后,從庫(kù)復(fù)制延遲逐漸增大到某個(gè)最高值之后突然變?yōu)?的情況

2、官方手冊(cè)中對(duì)主從拓?fù)涮幵谝粋€(gè)慢速網(wǎng)絡(luò)中表現(xiàn)行為描述不太準(zhǔn)確(個(gè)人推理觀點(diǎn)):

* 根據(jù)公式計(jì)算,如果主庫(kù)持續(xù)不斷產(chǎn)生二進(jìn)制日志(持續(xù)不斷有數(shù)據(jù)變更),則復(fù)制延遲的計(jì)算結(jié)果不會(huì)出現(xiàn)誤差(或者說(shuō)誤差可以忽略不計(jì),因?yàn)閺膸?kù)的系統(tǒng)時(shí)鐘是正常向后推進(jìn)的,除非主從庫(kù)的系統(tǒng)時(shí)間被改動(dòng)了),如果在慢速網(wǎng)絡(luò)中主庫(kù)斷斷續(xù)續(xù)寫(xiě)入數(shù)據(jù),甚至主庫(kù)突然停止任何數(shù)據(jù)寫(xiě)入,之后實(shí)際上主庫(kù)并沒(méi)有新的數(shù)據(jù)寫(xiě)入(也就不會(huì)有新的binlog event時(shí)間戳產(chǎn)生),但是由于計(jì)算公式中并不感知這個(gè)變化,所以隨著從庫(kù)的系統(tǒng)時(shí)鐘繼續(xù)向前推進(jìn),就會(huì)導(dǎo)致在追趕上主庫(kù)的數(shù)據(jù)之前,計(jì)算出的延遲時(shí)間值越來(lái)越大(也就是說(shuō)此時(shí)的復(fù)制延遲值是不可靠的)

作者寄語(yǔ):最后,感謝沃趣科技的同事 @劉云 幫忙做場(chǎng)景驗(yàn)證,感謝 @沈剛 幫忙查看源碼

加入知數(shù)堂

挑戰(zhàn)40萬(wàn)+年薪!

知數(shù)堂

葉金榮與吳炳錫聯(lián)合打造

領(lǐng)跑IT精英培訓(xùn)

行業(yè)資深專家強(qiáng)強(qiáng)聯(lián)合,傾心定制

MySQL的實(shí)戰(zhàn)/ MySQL的優(yōu)化/ MongoDB的/

Python / SQL優(yōu)化/ Hadoop + ELK

數(shù)門精品課程

“閱讀原文”可獲更多正課試聽(tīng)視頻

密碼:hg3h

緊隨技術(shù)發(fā)展趨勢(shì),定期優(yōu)化培訓(xùn)教案

融入大量生產(chǎn)案例,貼合企業(yè)一線需求

社群陪伴學(xué)習(xí),一次報(bào)名,可學(xué)1年

DBA,開(kāi)發(fā)工程師必修課

上千位學(xué)員已華麗轉(zhuǎn)身,薪資翻番,職位提升

改變已悄然發(fā)生,你還在等什么?

MySQL的入門到精通-ZST返回搜狐,查看更多

責(zé)任編輯:

總結(jié)

以上是生活随笔為你收集整理的mysql seconds_behind_master_MySQL 复制延迟 Seconds_Behind_Master 究竟是如何计算的的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。