一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數(shù)據(jù)庫(kù)技術(shù)|

服務(wù)器之家 - 數(shù)據(jù)庫(kù) - Mysql - 淺談如何保證Mysql主從一致

淺談如何保證Mysql主從一致

2022-03-10 17:21ZHY_ERIC Mysql

這篇文章主要介紹了淺談如何保證Mysql主從一致析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步

        為什么備庫(kù)執(zhí)行了 binlog 就可以跟主庫(kù)保持一致了呢?今天正式地和你介紹一下它。

        在最開始,MySQL 是以容易學(xué)習(xí)和方便的高可用架構(gòu),被開發(fā)人員青睞的。而它的幾乎所有的高可用架構(gòu),都直接依賴于 binlog。雖然這些高可用架構(gòu)已經(jīng)呈現(xiàn)出越來(lái)越復(fù)雜的趨勢(shì),但都是從最基本的一主一備演化過(guò)來(lái)的。

MySQL 主備的基本原理

淺談如何保證Mysql主從一致

圖 1 MySQL 主備切換流程

        在狀態(tài) 1 中,客戶端的讀寫都直接訪問(wèn)節(jié)點(diǎn) A,而節(jié)點(diǎn) B 是 A 的備庫(kù),只是將 A 的更新都同步過(guò)來(lái),到本地執(zhí)行。這樣可以保持節(jié)點(diǎn) B 和 A 的數(shù)據(jù)是相同的。

        當(dāng)需要切換的時(shí)候,就切成狀態(tài) 2。這時(shí)候客戶端讀寫訪問(wèn)的都是節(jié)點(diǎn) B,而節(jié)點(diǎn) A 是 B 的備庫(kù)。

        在狀態(tài) 1 中,雖然節(jié)點(diǎn) B 沒有被直接訪問(wèn),但是我依然建議你把節(jié)點(diǎn) B(也就是備庫(kù))設(shè)置成只讀(readonly)模式。這樣做,有以下幾個(gè)考慮:

  • 有時(shí)候一些運(yùn)營(yíng)類的查詢語(yǔ)句會(huì)被放到備庫(kù)上去查,設(shè)置為只讀可以防止誤操作;
  • 防止切換邏輯有 bug,比如切換過(guò)程中出現(xiàn)雙寫,造成主備不一致;
  • 可以用 readonly 狀態(tài),來(lái)判斷節(jié)點(diǎn)的角色。

        你可能會(huì)問(wèn),我把備庫(kù)設(shè)置成只讀了,還怎么跟主庫(kù)保持同步更新呢?

        這個(gè)問(wèn)題,你不用擔(dān)心。因?yàn)?readonly 設(shè)置對(duì)超級(jí) (super) 權(quán)限用戶是無(wú)效的,而用于同步更新的線程,就擁有超級(jí)權(quán)限。

        接下來(lái),我們?cè)倏纯?strong>節(jié)點(diǎn) A 到 B 這條線的內(nèi)部流程是什么樣的。圖 2 中畫出的就是一個(gè) update 語(yǔ)句在節(jié)點(diǎn) A 執(zhí)行,然后同步到節(jié)點(diǎn) B 的完整流程圖。

淺談如何保證Mysql主從一致

圖 2 主備流程圖

       圖 2 中,包含了在上一篇文章中講到的 binlog 和 redo log 的寫入機(jī)制相關(guān)的內(nèi)容,可以看到:主庫(kù)接收到客戶端的更新請(qǐng)求后,執(zhí)行內(nèi)部事務(wù)的更新邏輯,同時(shí)寫 binlog。

        備庫(kù) B 跟主庫(kù) A 之間維持了一個(gè)長(zhǎng)連接。主庫(kù) A 內(nèi)部有一個(gè)線程,專門用于服務(wù)備庫(kù) B 的這個(gè)長(zhǎng)連接。一個(gè)事務(wù)日志同步的完整過(guò)程是這樣的:

  • 在備庫(kù) B 上通過(guò) change master 命令,設(shè)置主庫(kù) A 的 IP、端口、用戶名、密碼,以及要從哪個(gè)位置開始請(qǐng)求 binlog,這個(gè)位置包含文件名和日志偏移量。
  • 在備庫(kù) B 上執(zhí)行 start slave 命令,這時(shí)候備庫(kù)會(huì)啟動(dòng)兩個(gè)線程,就是圖中的 io_thread 和 sql_thread。其中 io_thread 負(fù)責(zé)與主庫(kù)建立連接。
  • 主庫(kù) A 校驗(yàn)完用戶名、密碼后,開始按照備庫(kù) B 傳過(guò)來(lái)的位置,從本地讀取 binlog,發(fā)給 B。
  • 備庫(kù) B 拿到 binlog 后,寫到本地文件,稱為中轉(zhuǎn)日志(relay log)。
  • sql_thread 讀取中轉(zhuǎn)日志,解析出日志里的命令,并執(zhí)行。

 

binlog 的三種格式對(duì)比

         binlog 有兩種格式,一種是 statement,一種是 row。可能你在其他資料上還會(huì)看到有第三種格式,叫作 mixed,其實(shí)它就是前兩種格式的混合。

        為了便于描述 binlog 的這三種格式間的區(qū)別,創(chuàng)建了一個(gè)表,并初始化幾行數(shù)據(jù)。

mysql> CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `a` int(11) DEFAULT NULL,
  `t_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `a` (`a`),
  KEY `t_modified`(`t_modified`)
) ENGINE=InnoDB;
 
insert into t values(1,1,"2018-11-13");
insert into t values(2,2,"2018-11-12");
insert into t values(3,3,"2018-11-11");
insert into t values(4,4,"2018-11-10");
insert into t values(5,5,"2018-11-09");

         如果要在表中刪除一行數(shù)據(jù)的話,我們來(lái)看看這個(gè) delete 語(yǔ)句的 binlog 是怎么記錄的。

        下面這個(gè)語(yǔ)句包含注釋,如果你用 MySQL 客戶端來(lái)做這個(gè)實(shí)驗(yàn)的話,要記得加 -c 參數(shù),否則客戶端會(huì)自動(dòng)去掉注釋。

mysql> delete from t /*comment*/ where a>=4 and t_modified<="2018-11-10" limit 1;

         當(dāng) binlog_format=statement 時(shí),binlog 里面記錄的就是 SQL 語(yǔ)句的原文。你可以用

mysql> show binlog events in "master.000001";

         命令看 binlog 中的內(nèi)容。

淺談如何保證Mysql主從一致

圖 3 statement 格式 binlog 示例

  • 第一行 SET @@SESSION.GTID_NEXT='ANONYMOUS’你可以先忽略,后面文章會(huì)在介紹主備切換的時(shí)候再提到;
  • 第二行是一個(gè) BEGIN,跟第四行的 commit 對(duì)應(yīng),表示中間是一個(gè)事務(wù);
  • 第三行就是真實(shí)執(zhí)行的語(yǔ)句了。可以看到,在真實(shí)執(zhí)行的 delete 命令之前,還有一個(gè)“use ‘test’”命令。這條命令不是我們主動(dòng)執(zhí)行的,而是 MySQL 根據(jù)當(dāng)前要操作的表所在的數(shù)據(jù)庫(kù),自行添加的。這樣做可以保證日志傳到備庫(kù)去執(zhí)行的時(shí)候,不論當(dāng)前的工作線程在哪個(gè)庫(kù)里,都能夠正確地更新到 test 庫(kù)的表 t。
  • use 'test’命令之后的 delete 語(yǔ)句,就是我們輸入的 SQL 原文了。可以看到,binlog“忠實(shí)”地記錄了 SQL 命令,甚至連注釋也一并記錄了。
  • 最后一行是一個(gè) COMMIT。你可以看到里面寫著 xid=61。你還記得這個(gè) XID 是做什么用的嗎?

        為了說(shuō)明 statement 和 row 格式的區(qū)別,我們來(lái)看一下這條 delete 命令的執(zhí)行效果圖:

淺談如何保證Mysql主從一致

圖 4 delete 執(zhí)行 warnings

         運(yùn)行這條 delete 命令產(chǎn)生了一個(gè) warning,原因是當(dāng)前 binlog 設(shè)置的是 statement 格式,并且語(yǔ)句中有 limit,所以這個(gè)命令可能是 unsafe 的。

        這是因?yàn)?delete 帶 limit,很可能會(huì)出現(xiàn)主備數(shù)據(jù)不一致的情況。比如上面這個(gè)例子:

  • 如果 delete 語(yǔ)句使用的是索引 a,那么會(huì)根據(jù)索引 a 找到第一個(gè)滿足條件的行,也就是說(shuō)刪除的是 a=4 這一行;
  • 但如果使用的是索引 t_modified,那么刪除的就是 t_modified='2018-11-09’也就是 a=5 這一行。

        由于 statement 格式下,記錄到 binlog 里的是語(yǔ)句原文,因此可能會(huì)出現(xiàn)這樣一種情況:在主庫(kù)執(zhí)行這條 SQL 語(yǔ)句的時(shí)候,用的是索引 a;而在備庫(kù)執(zhí)行這條 SQL 語(yǔ)句的時(shí)候,卻使用了索引 t_modified。因此,MySQL 認(rèn)為這樣寫是有風(fēng)險(xiǎn)的。

        那么,如果我把 binlog 的格式改為 binlog_format=‘row’, 是不是就沒有這個(gè)問(wèn)題了呢?

淺談如何保證Mysql主從一致

圖 5 row 格式 binlog 示例 

         與 statement 格式的 binlog 相比,前后的 BEGIN 和 COMMIT 是一樣的。但是,row 格式的 binlog 里沒有了 SQL 語(yǔ)句的原文,而是替換成了兩個(gè) event:Table_map 和 Delete_rows。

  • Table_map event,用于說(shuō)明接下來(lái)要操作的表是 test 庫(kù)的表 t;
  • Delete_rows event,用于定義刪除的行為

        其實(shí),我們通過(guò)圖 5 是看不到詳細(xì)信息的,還需要借助 mysqlbinlog 工具,用下面這個(gè)命令解析和查看 binlog 中的內(nèi)容。因?yàn)閳D 5 中的信息顯示,這個(gè)事務(wù)的 binlog 是從 8900 這個(gè)位置開始的,所以可以用 start-position 參數(shù)來(lái)指定從這個(gè)位置的日志開始解析。

mysqlbinlog -vv data/master.000001 --start-position=8900;

淺談如何保證Mysql主從一致

圖 6 row 格式 binlog 示例的詳細(xì)信息 

        從這個(gè)圖中,我們可以看到以下幾個(gè)信息:

  • server id 1,表示這個(gè)事務(wù)是在 server_id=1 的這個(gè)庫(kù)上執(zhí)行的。
  • 每個(gè) event 都有 CRC32 的值,這是因?yàn)槲野褏?shù) binlog_checksum 設(shè)置成了 CRC32。
  • Table_map event 跟在圖 5 中看到的相同,顯示了接下來(lái)要打開的表,map 到數(shù)字 226。現(xiàn)在我們這條 SQL 語(yǔ)句只操作了一張表,如果要操作多張表呢?每個(gè)表都有一個(gè)對(duì)應(yīng)的 Table_map event、都會(huì) map 到一個(gè)單獨(dú)的數(shù)字,用于區(qū)分對(duì)不同表的操作。
  • 我們?cè)?mysqlbinlog 的命令中,使用了 -vv 參數(shù)是為了把內(nèi)容都解析出來(lái),所以從結(jié)果里面可以看到各個(gè)字段的值(比如,@1=4、 @2=4 這些值)。
  • binlog_row_image 的默認(rèn)配置是 FULL,因此 Delete_event 里面,包含了刪掉的行的所有字段的值。如果把 binlog_row_image 設(shè)置為 MINIMAL,則只會(huì)記錄必要的信息,在這個(gè)例子里,就是只會(huì)記錄 id=4 這個(gè)信息。
  • 最后的 Xid event,用于表示事務(wù)被正確地提交了。

        當(dāng) binlog_format 使用 row 格式的時(shí)候,binlog 里面記錄了真實(shí)刪除行的主鍵 id,這樣 binlog 傳到備庫(kù)去的時(shí)候,就肯定會(huì)刪除 id=4 的行,不會(huì)有主備刪除不同行的問(wèn)題。

 

為什么會(huì)有 mixed 格式的 binlog?

        基于上面的信息,我們來(lái)討論一個(gè)問(wèn)題:為什么會(huì)有 mixed 這種 binlog 格式的存在場(chǎng)景?推論過(guò)程是這樣的:

  • 因?yàn)橛行?statement 格式的 binlog 可能會(huì)導(dǎo)致主備不一致,所以要使用 row 格式。
  • 但 row 格式的缺點(diǎn)是,很占空間。比如你用一個(gè) delete 語(yǔ)句刪掉 10 萬(wàn)行數(shù)據(jù),用 statement 的話就是一個(gè) SQL 語(yǔ)句被記錄到 binlog 中,占用幾十個(gè)字節(jié)的空間。但如果用 row 格式的 binlog,就要把這 10 萬(wàn)條記錄都寫到 binlog 中。這樣做,不僅會(huì)占用更大的空間,同時(shí)寫 binlog 也要耗費(fèi) IO 資源,影響執(zhí)行速度。
  • 所以,MySQL 就取了個(gè)折中方案,也就是有了 mixed 格式的 binlog。mixed 格式的意思是,MySQL 自己會(huì)判斷這條 SQL 語(yǔ)句是否可能引起主備不一致,如果有可能,就用 row 格式,否則就用 statement 格式。

        也就是說(shuō),mixed 格式可以利用 statment 格式的優(yōu)點(diǎn),同時(shí)又避免了數(shù)據(jù)不一致的風(fēng)險(xiǎn)。

        因此,如果你的線上 MySQL 設(shè)置的 binlog 格式是 statement 的話,那基本上就可以認(rèn)為這是一個(gè)不合理的設(shè)置。你至少應(yīng)該把 binlog 的格式設(shè)置為 mixed。

        現(xiàn)在越來(lái)越多的場(chǎng)景要求把 MySQL 的 binlog 格式設(shè)置成 row。這么做的理由有很多,我來(lái)給你舉一個(gè)可以直接看出來(lái)的好處:恢復(fù)數(shù)據(jù)

        接下來(lái),我們就分別從 delete、insert 和 update 這三種 SQL 語(yǔ)句的角度,來(lái)看看數(shù)據(jù)恢復(fù)的問(wèn)題。

        通過(guò)圖 6 你可以看出來(lái),即使我執(zhí)行的是 delete 語(yǔ)句,row 格式的 binlog 也會(huì)把被刪掉的行的整行信息保存起來(lái)。所以,如果你在執(zhí)行完一條 delete 語(yǔ)句以后,發(fā)現(xiàn)刪錯(cuò)數(shù)據(jù)了,可以直接把 binlog 中記錄的 delete 語(yǔ)句轉(zhuǎn)成 insert,把被錯(cuò)刪的數(shù)據(jù)插入回去就可以恢復(fù)了。

        如果你是執(zhí)行錯(cuò)了 insert 語(yǔ)句呢?那就更直接了。row 格式下,insert 語(yǔ)句的 binlog 里會(huì)記錄所有的字段信息,這些信息可以用來(lái)精確定位剛剛被插入的那一行。這時(shí),你直接把 insert 語(yǔ)句轉(zhuǎn)成 delete 語(yǔ)句,刪除掉這被誤插入的一行數(shù)據(jù)就可以了。

        如果執(zhí)行的是 update 語(yǔ)句的話,binlog 里面會(huì)記錄修改前整行的數(shù)據(jù)和修改后的整行數(shù)據(jù)。所以,如果你誤執(zhí)行了 update 語(yǔ)句的話,只需要把這個(gè) event 前后的兩行信息對(duì)調(diào)一下,再去數(shù)據(jù)庫(kù)里面執(zhí)行,就能恢復(fù)這個(gè)更新操作了。

        其實(shí),由 delete、insert 或者 update 語(yǔ)句導(dǎo)致的數(shù)據(jù)操作錯(cuò)誤,需要恢復(fù)到操作之前狀態(tài)的情況,也時(shí)有發(fā)生。MariaDB 的Flashback工具就是基于上面介紹的原理來(lái)回滾數(shù)據(jù)的。

        雖然 mixed 格式的 binlog 現(xiàn)在已經(jīng)用得不多了,但這里我還是要再借用一下 mixed 格式來(lái)說(shuō)明一個(gè)問(wèn)題,來(lái)看一下這條 SQL 語(yǔ)句:

mysql> insert into t values(10,10, now());

         如果我們把 binlog 格式設(shè)置為 mixed,你覺得 MySQL 會(huì)把它記錄為 row 格式還是 statement 格式呢?

        先不要著急說(shuō)結(jié)果,我們一起來(lái)看一下這條語(yǔ)句執(zhí)行的效果。

淺談如何保證Mysql主從一致

圖 7 mixed 格式和 now() 

        可以看到,MySQL 用的居然是 statement 格式。你一定會(huì)奇怪,如果這個(gè) binlog 過(guò)了 1 分鐘才傳給備庫(kù)的話,那主備的數(shù)據(jù)不就不一致了嗎?

        接下來(lái),我們?cè)儆?mysqlbinlog 工具來(lái)看看:

淺談如何保證Mysql主從一致

圖 8 TIMESTAMP 命令 

        從圖中的結(jié)果可以看到,原來(lái) binlog 在記錄 event 的時(shí)候,多記了一條命令:SET TIMESTAMP=1546103491。它用 SET TIMESTAMP 命令約定了接下來(lái)的 now() 函數(shù)的返回時(shí)間。

        因此,不論這個(gè) binlog 是 1 分鐘之后被備庫(kù)執(zhí)行,還是 3 天后用來(lái)恢復(fù)這個(gè)庫(kù)的備份,這個(gè) insert 語(yǔ)句插入的行,值都是固定的。也就是說(shuō),通過(guò)這條 SET TIMESTAMP 命令,MySQL 就確保了主備數(shù)據(jù)的一致性。我之前看過(guò)有人在重放 binlog 數(shù)據(jù)的

        之前看過(guò)有人在重放 binlog 數(shù)據(jù)的時(shí)候,是這么做的:用 mysqlbinlog 解析出日志,然后把里面的 statement 語(yǔ)句直接拷貝出來(lái)執(zhí)行。你現(xiàn)在知道了,這個(gè)方法是有風(fēng)險(xiǎn)的。因?yàn)橛行┱Z(yǔ)句的執(zhí)行結(jié)果是依賴于上下文命令的,直接執(zhí)行的結(jié)果很可能是錯(cuò)誤的。

        所以,用 binlog 來(lái)恢復(fù)數(shù)據(jù)的標(biāo)準(zhǔn)做法是,用 mysqlbinlog 工具解析出來(lái),然后把解析結(jié)果整個(gè)發(fā)給 MySQL 執(zhí)行。類似下面的命令

mysqlbinlog master.000001 --start-position=2738 --stop-position=2973 | mysql -h127.0.0.1 -P13000 -u$user -p$pwd;

 

 循環(huán)復(fù)制問(wèn)題

        我們可以認(rèn)為正常情況下主備的數(shù)據(jù)是一致的。也就是說(shuō),圖 1 中 A、B 兩個(gè)節(jié)點(diǎn)的內(nèi)容是一致的。其實(shí),圖 1 中的是 M-S 結(jié)構(gòu),但實(shí)際生產(chǎn)上使用比較多的是雙 M 結(jié)構(gòu),也就是圖 9 所示的主備切換流程。

淺談如何保證Mysql主從一致

圖 9 MySQL 主備切換流程 -- 雙 M 結(jié)構(gòu)

        對(duì)比圖 9 和圖 1,你可以發(fā)現(xiàn),雙 M 結(jié)構(gòu)和 M-S 結(jié)構(gòu),其實(shí)區(qū)別只是多了一條線,即:節(jié)點(diǎn) A 和 B 之間總是互為主備關(guān)系。這樣在切換的時(shí)候就不用再修改主備關(guān)系。

        但是,雙 M 結(jié)構(gòu)還有一個(gè)問(wèn)題需要解決。

        業(yè)務(wù)邏輯在節(jié)點(diǎn) A 上更新了一條語(yǔ)句,然后再把生成的 binlog 發(fā)給節(jié)點(diǎn) B,節(jié)點(diǎn) B 執(zhí)行完這條更新語(yǔ)句后也會(huì)生成 binlog。(我建議你把參數(shù) log_slave_updates 設(shè)置為 on,表示備庫(kù)執(zhí)行 relay log 后生成 binlog)

        那么,如果節(jié)點(diǎn) A 同時(shí)是節(jié)點(diǎn) B 的備庫(kù),相當(dāng)于又把節(jié)點(diǎn) B 新生成的 binlog 拿過(guò)來(lái)執(zhí)行了一次,然后節(jié)點(diǎn) A 和 B 間,會(huì)不斷地循環(huán)執(zhí)行這個(gè)更新語(yǔ)句,也就是循環(huán)復(fù)制了。這個(gè)要怎么解決呢?

        從上面的圖 6 中可以看到,MySQL 在 binlog 中記錄了這個(gè)命令第一次執(zhí)行時(shí)所在實(shí)例的 server id。因此,我們可以用下面的邏輯,來(lái)解決兩個(gè)節(jié)點(diǎn)間的循環(huán)復(fù)制的問(wèn)題:

  • 規(guī)定兩個(gè)庫(kù)的 server id 必須不同,如果相同,則它們之間不能設(shè)定為主備關(guān)系;
  • 一個(gè)備庫(kù)接到 binlog 并在重放的過(guò)程中,生成與原 binlog 的 server id 相同的新的 binlog;
  • 每個(gè)庫(kù)在收到從自己的主庫(kù)發(fā)過(guò)來(lái)的日志后,先判斷 server id,如果跟自己的相同,表示這個(gè)日志是自己生成的,就直接丟棄這個(gè)日志。

        按照這個(gè)邏輯,如果我們?cè)O(shè)置了雙 M 結(jié)構(gòu),日志的執(zhí)行流就會(huì)變成這樣:

  • 從節(jié)點(diǎn) A 更新的事務(wù),binlog 里面記的都是 A 的 server id;
  • 傳到節(jié)點(diǎn) B 執(zhí)行一次以后,節(jié)點(diǎn) B 生成的 binlog 的 server id 也是 A 的 server id;
  • 再傳回給節(jié)點(diǎn) A,A 判斷到這個(gè) server id 與自己的相同,就不會(huì)再處理這個(gè)日志。所以,死循環(huán)在這里就斷掉了。

 

小結(jié)

        binlog 在 MySQL 的各種高可用方案上扮演了重要角色。今天介紹的可以說(shuō)是所有 MySQL 高可用方案的基礎(chǔ)。在這之上演化出了諸如多節(jié)點(diǎn)、半同步、MySQL group replication 等相對(duì)復(fù)雜的方案。

思考題: 說(shuō)到循環(huán)復(fù)制問(wèn)題的時(shí)候,我們說(shuō) MySQL 通過(guò)判斷 server id 的方式,斷掉死循環(huán)。但是,這個(gè)機(jī)制其實(shí)并不完備,在某些場(chǎng)景下,還是有可能出現(xiàn)死循環(huán)?又應(yīng)該怎么解決呢?

        答案:一種場(chǎng)景是,在一個(gè)主庫(kù)更新事務(wù)后,用命令 set global server_id=x 修改了 server_id。等日志再傳回來(lái)的時(shí)候,發(fā)現(xiàn) server_id 跟自己的 server_id 不同,就只能執(zhí)行了。

        另一種場(chǎng)景是,有三個(gè)節(jié)點(diǎn)的時(shí)候,如圖 7 所示,trx1 是在節(jié)點(diǎn) B 執(zhí)行的,因此 binlog 上的 server_id 就是 B,binlog 傳給節(jié)點(diǎn) A,然后 A 和 A’搭建了雙 M 結(jié)構(gòu),就會(huì)出現(xiàn)循環(huán)復(fù)制。

到此這篇關(guān)于淺談如何保證Mysql主從一致的文章就介紹到這了,更多相關(guān)Mysql 主從一致內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文地址:https://blog.csdn.net/ZHY_ERIC/article/details/123344246

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美激情亚洲 | 四虎精品免费国产成人 | 国产亚洲欧美成人久久片 | 高中生喷水喷浆 | 福利视频久久 | 成人免费淫片95视频观看网站 | 2020年国产精品午夜福利在线观看 | 欧美日韩高清完整版在线观看免费 | 婷婷婷色 | 午夜精品久久久久久久99蜜桃i | 成人免费播放 | 免费日批| 全彩孕交漫画福利啪啪吧 | 婚前试爱免费看 | 本土自拍 | 精品日韩欧美一区二区三区在线播放 | 青青在线国产视频 | 午夜精品久久久久久久99蜜桃i | 亚洲区一 | 校草太大了h| 亚洲国产在线观看免费视频 | 日韩a级片视频 | 妹妹骑上来蹭着蹭着就射了 | xx欧美老妇 | 91精品国产美女福到在线不卡 | 午夜国产在线 | 欧美一级高清免费a | 欧美xingai | 无码AV精品一区二区三区 | 男人的天堂久久精品激情a 男人的天堂va | 好吊妞视频998www | 精品国产福利在线观看一区 | lilisha李丽莎喷水大胆在线 | 好吊色视频988gao在线观看 | 99精品视频一区在线观看miya | 色综合久久中文字幕综合网 | 60老妇性xxxxhd | 好湿好紧太硬了我太爽了h 好湿好滑好硬好爽好深视频 | 99精品国产久热在线观看66 | 波多野 在线 | 摸逼网|