<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          聽(tīng)我講完 redo log、binlog 原理,面試官老臉一紅!

          共 7059字,需瀏覽 15分鐘

           ·

          2021-09-06 08:15

          上一篇:一個(gè)90后員工猝死的全過(guò)程
          0、2T架構(gòu)師學(xué)習(xí)資料干貨分享

          我有一個(gè)老朋友,我們叫他熊貓。發(fā)際線(xiàn)及將觸碰到后腦勺,大框金絲眼鏡也掩蓋不住那黝黑的眼圈,顯得格外的“程序員”;穿著也非常不拘一格,上半身是襯衣西服,下半身是牛仔褲配拖鞋~

          我和熊貓的感情很好,畢業(yè)后他去了上海而我開(kāi)始北漂,但每次過(guò)節(jié)回老家我倆都會(huì)和朋友們一起吃飯,這次回家過(guò)年也不例外。這次,我們朋友幾個(gè)去了棗莊出名的“好再來(lái)土菜館”,點(diǎn)了特色的棗莊辣子雞,超大盤(pán)那種。

          這次在飯桌上,我們聊到了疫情期間我們幾個(gè)積極參加各大廠(chǎng)免費(fèi)面試的一些有趣場(chǎng)景。熊貓說(shuō)在面試一家數(shù)據(jù)存儲(chǔ)的大廠(chǎng)時(shí),深挖了一個(gè)MySQL問(wèn)題,redo log和 binlog,很有意思。

          面試官也很客氣,總有種莫名的親切感。說(shuō)著,翹起二郎腿喊道:“老板,再來(lái)一箱青島”!我們幾個(gè)都知道,熊貓又要開(kāi)始回放了~~另外,MySQL 系列面試題和答案全部整理好了,微信搜索互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)發(fā)送:2T,可以在線(xiàn)閱讀。

          以下是熊貓和面試官馬經(jīng)理的對(duì)話(huà)。

          熊貓:馬…小馬哥好!

          面試官:額…你好,小李啊,看你簡(jiǎn)歷寫(xiě)著精通MySQL事務(wù)、日志原理,你認(rèn)為精通應(yīng)該是啥水平呢?

          熊貓(老臉一紅):emmm…精通就是,比面試官知道的多一點(diǎn)唄。。

          面試官:(嗯。。。。是個(gè)老實(shí)人,我喜歡!)

          面試官:那你先給我講講MySQL里有哪些比較重要的日志吧?

          熊貓:(我只看了redo log、binlog面試題,咋整,多說(shuō)會(huì)不會(huì)給自己挖坑?記得魯迅大爺說(shuō)過(guò):別啥JB都說(shuō),最后坑自己)

          熊貓:嗯。。其實(shí)MySQL中的日志有很多,但日常接觸最多的是重做日志(redo log)、歸檔日志(binlog)這兩種,當(dāng)然還有回滾日志(undo log)等等,我接觸的少一些。

          MySQL日志主要包括六種:

          1. 重做日志(redo log)
          2. 回滾日志(undo log)
          3. 歸檔日志(binlog)
          4. 錯(cuò)誤日志(errorlog)
          5. 慢查詢(xún)?nèi)罩荆╯low query log)
          6. 一般查詢(xún)?nèi)罩荆╣eneral log)
          7. 中繼日志(relay log)

          面試官:好,那你先說(shuō)一下你對(duì) redo log 日志的理解吧。

          熊貓:記得小時(shí)候看《武林外傳》,呂秀才柜臺(tái)下面有一個(gè)小黑板,當(dāng)時(shí)不知道是干啥的,后來(lái)發(fā)現(xiàn)是專(zhuān)門(mén)用來(lái)記錄客人的賒賬記錄。如果賒賬的人不多,那么他可以把顧客名和賬目寫(xiě)在板上。但如果賒賬的人多了,小黑板沒(méi)地兒了,這個(gè)時(shí)秀才一定還有一個(gè)專(zhuān)門(mén)記錄賒賬的賬本。如果有人要賒賬或者還賬的話(huà),秀才一般有兩種做法:

          在生意火爆時(shí),秀才肯定會(huì)選擇后者,因?yàn)橹苯佑涃~本太麻煩了。得先翻出賒賬人“老錢(qián)”那條記錄,賬本密密麻麻幾十頁(yè),找到后再拿出算盤(pán)計(jì)算,最后更新到賬本上。

          想想都麻煩。相比之下,還是先在小黑板上記一下方便。你想想,如果秀才沒(méi)有小黑板的幫助,每次記賬都得翻賬本,效率是不是低得讓人難以忍受?還有時(shí)間泡小郭?想無(wú)雙?

          同樣,在 MySQL 里也有這個(gè)問(wèn)題,如果每一次的更新操作都需要寫(xiě)進(jìn)磁盤(pán),然后磁盤(pán)也要找到對(duì)應(yīng)的那條記錄,然后再更新,整個(gè)過(guò)程 IO 成本、查找成本都很高。為了解決這個(gè)問(wèn)題,MySQL 的設(shè)計(jì)者就用了類(lèi)似秀才記小黑板的思路來(lái)提升更新效率。

          另外,MySQL 系列面試題和答案全部整理好了,微信搜索互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)發(fā)送:2T,可以在線(xiàn)閱讀。

          而小黑板和賬本配合的過(guò)程,其實(shí)就是 MySQL 里經(jīng)常說(shuō)到的 WAL 技術(shù)

          面試官:小伙子你這思路很奇特呀!那你再詳細(xì)跟我說(shuō)一下,啥是WAL技術(shù)?

          熊貓:(小馬哥對(duì)我有意思啊!)

          WAL 的全稱(chēng)是 Write-Ahead Logging,它的關(guān)鍵點(diǎn)就是先寫(xiě)日志,再寫(xiě)磁盤(pán),也就是先寫(xiě)小黑板,等不忙的時(shí)候再寫(xiě)賬本。

          具體來(lái)說(shuō),當(dāng)有一條update語(yǔ)句要執(zhí)行的時(shí)候,InnoDB 引擎就會(huì)先把記錄寫(xiě)到 redo log(小黑板)里面,并更新內(nèi)存,這個(gè)時(shí)候更新就算完成了。

          同時(shí),InnoDB引擎會(huì)在適當(dāng)?shù)臅r(shí)候,將這個(gè)操作記錄更新到磁盤(pán)里面,而這個(gè)更新往往是在系統(tǒng)比較空閑的時(shí)候做,這就像打烊以后秀才做的事。如果今天賒賬的不多,掌柜可以等打烊后再整理。

          但如果某天賒賬的特別多,小黑板寫(xiě)滿(mǎn)了咋辦?這個(gè)時(shí)候秀才只好叫無(wú)雙幫忙干自己的活兒,抓緊把小黑板中的一部分賒賬記錄更新到賬本中,然后把這些記錄從小黑板上擦掉,為記新賬騰出空間。

          與此類(lèi)似,InnoDB 的 redo log 是固定大小的,比如可以配置為一組 4 個(gè)文件,每個(gè)文件的大小是 100MB,那么這塊“小黑板”總共就可以記錄 400MB 的操作記錄。從頭開(kāi)始寫(xiě),寫(xiě)到末尾就又回到開(kāi)頭循環(huán)寫(xiě),如下面這個(gè)圖所示。

          write position 和 checkpoint 之間的是“小黑板”上還空著的部分,可以用來(lái)記錄新的操作。

          如果 write pos 追上 checkpoint,表示“小黑板”滿(mǎn)了,這時(shí)候不能再執(zhí)行新的更新,得停下來(lái)先擦掉一些記錄,把 checkpoint 推進(jìn)一下。

          有了 redo log,InnoDB 就可以保證即使數(shù)據(jù)庫(kù)發(fā)生異常重啟,之前提交的記錄都不會(huì)丟失,這個(gè)能力稱(chēng)為 crash-safe

          crash-safe:可以對(duì)照前面賒賬記錄的例子。只要賒賬記錄記在了小黑板上或?qū)懺诹速~本上,即使秀才突然被老邢抓走幾天,回來(lái)后依然可以通過(guò)賬本和小黑板上的數(shù)據(jù)明確賒賬賬目。就是維護(hù)數(shù)據(jù)的持久性。

          本質(zhì)上說(shuō),crash-safe 就是落盤(pán)處理,將數(shù)據(jù)存儲(chǔ)到了磁盤(pán)上,斷電重啟也不會(huì)丟失。

          面試官:不錯(cuò),你這理解雖說(shuō)聽(tīng)的我一愣一愣,但是話(huà)糙理不糙,確實(shí)說(shuō)出了redo log的原理。那你再說(shuō)說(shuō)對(duì)binlog日志的理解吧。

          熊貓:嘿嘿,謝謝馬經(jīng)理夸獎(jiǎng)。MySQL 其實(shí)是分為 server層 和 引擎層兩部分。

          上面我們聊到的“小黑板” redo log 是 InnoDB 引擎特有的日志,而 Server 層也有自己的日志,稱(chēng)為binlog(歸檔日志),其實(shí)就是用來(lái)恢復(fù)數(shù)據(jù)用的。

          面試官:那MySQL為啥要有redo log 和 binlog兩個(gè)日志呢?只留一個(gè)不香么?

          熊貓:因?yàn)樽铋_(kāi)始 MySQL 里并沒(méi)有 InnoDB 引擎。MySQL 自帶的引擎是 MyISAM,但是 MyISAM 沒(méi)有 crash-safe 的能力,而 binlog 日志只用于歸檔。

          InnoDB 是另一個(gè)公司以插件形式引入 MySQL 的。我們知道,只依靠 binlog 是沒(méi)有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系統(tǒng)——也就是 redo log 來(lái)實(shí)現(xiàn) crash-safe 能力。

          面試官:那這兩個(gè)日志主要有哪些區(qū)別?

          熊貓:emmm…主要有幾下幾種區(qū)別:

          1. redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 層實(shí)現(xiàn)的,所有引擎共用。
          2. redo log 是物理日志,記錄的是“在某個(gè)數(shù)據(jù)頁(yè)上做了什么修改”;binlog 是邏輯日志,記錄的是這個(gè)語(yǔ)句的原始邏輯,比如“給 ID=1 這一行的 c 字段加 1 ”。
          3. redo log 是循環(huán)寫(xiě)的,空間固定會(huì)用完然后復(fù)寫(xiě);binlog 是可以追加寫(xiě)入的。“追加寫(xiě)”是指 binlog 文件寫(xiě)到一定大小后會(huì)切換到下一個(gè),并不會(huì)覆蓋以前的日志。
          面試官:好,基于你上面說(shuō)的,那比如下面這條SQL,你來(lái)描述一下在MySQL內(nèi)部的執(zhí)行流程吧
          update T set money = money + 500 where username = '陳哈哈';
          熊貓
          1. (開(kāi)始,原始數(shù)據(jù)接入)執(zhí)行器先找引擎取 username = ‘陳哈哈’ 這一行。如果 username = ‘陳哈哈’ 這一行所在的數(shù)據(jù)頁(yè)本來(lái)就在內(nèi)存中,就直接返回給執(zhí)行器;否則,需要先從磁盤(pán)讀入內(nèi)存,然后再返回。
          2. (數(shù)據(jù)修改)執(zhí)行器拿到引擎給的行數(shù)據(jù),把 money 這字段的值加上 500,比如原來(lái)是 N,現(xiàn)在就是 N+500,得到新的一行數(shù)據(jù),再調(diào)用引擎接口寫(xiě)入這行新數(shù)據(jù)。
          3. (數(shù)據(jù)提交)提交操作,由于存儲(chǔ)引擎層與server層之間采用的是內(nèi)部XA(保證兩個(gè)事務(wù)的一致性,這里主要保證redo log和binlog的原子性),所以提交分為prepare階段與commit階段,也就是我們說(shuō)的兩階段提交
          4. (寫(xiě)redo log)引擎將這行新數(shù)據(jù)更新到內(nèi)存中,同時(shí)將這個(gè)更新操作記錄到 redo log 里面(寫(xiě)到內(nèi)存或直接落盤(pán)),到這里, redo log 處于 prepare 狀態(tài)。
          5. (寫(xiě)binlog)然后告知執(zhí)行器執(zhí)行完成了,隨時(shí)可以提交事務(wù)。執(zhí)行器生成這個(gè)操作的 binlog,并把 binlog 同步到磁盤(pán)。
          6. (數(shù)據(jù)更新到磁盤(pán)或內(nèi)存,結(jié)束)執(zhí)行器調(diào)用引擎的提交事務(wù)接口執(zhí)行修改操作,需要將在二級(jí)索引上做的修改,寫(xiě)入到change buffer page,等到下次有其他sql需要讀取該二級(jí)索引時(shí),再去與二級(jí)索引做merge,引擎把剛剛寫(xiě)入的 redo log 標(biāo)記上(commit)狀態(tài),實(shí)際上是加上了一個(gè)與binlog對(duì)應(yīng)的XID,使兩個(gè)日志邏輯保持一致,到此結(jié)束,更新流程閉環(huán)。

          面試官:那為啥必須要分成prepare和commit兩個(gè)階段進(jìn)行提交呢?一塊兒提交他不爽么。

          熊貓:我舉個(gè)現(xiàn)實(shí)生活中的栗子吧,一個(gè)完整的交易過(guò)程我認(rèn)為應(yīng)該這樣:

          比如你來(lái)我的小超市里買(mǎi)一瓶可樂(lè):

          1. 小馬哥:老板給我來(lái)瓶可樂(lè)!透心涼心飛揚(yáng)的那個(gè)。
          2. 我:??
          3. 機(jī)器掃一下可樂(lè),告訴小馬哥這瓶可樂(lè)2塊5,不能白嫖,讓他給錢(qián)(記錄 redo log,事務(wù)處于prepare狀態(tài))
          4. 收錢(qián)放入錢(qián)箱(記錄 binlog,事務(wù)實(shí)際是否完成的根本依據(jù),處于待標(biāo)記commit階段)
          5. 然后讓你把可樂(lè)拿走(redo log 狀態(tài)標(biāo)為 commit,表示該事務(wù)邏輯閉環(huán))。到這里,代表一筆交易結(jié)束
          6. 并告訴小馬哥,透心涼心飛揚(yáng)那個(gè)是雪碧,你個(gè)憨X~
          7. 等算賬前再把這一天賣(mài)東西的交易信息一起同步到數(shù)據(jù)庫(kù)。
          可見(jiàn),如果收錢(qián)之前(prepare階段,步驟3)交易被打斷,回過(guò)頭來(lái)處理此次交易,發(fā)現(xiàn)只有記了小黑板但沒(méi)有收錢(qián),則交易失敗,刪掉小黑板上的記錄(回滾);

          如果收了錢(qián)后(commit階段 或 待commit階段,步驟4 || 5)交易被打斷,然后回過(guò)頭發(fā)現(xiàn)系統(tǒng)上有記錄(prepare)而且錢(qián)箱有本次收入(bin log),則說(shuō)明本次交易有效,補(bǔ)充修改commit狀態(tài),更新到庫(kù)存中。


          以上是人話(huà),咱們?cè)賮?lái)看看MySQL層面的專(zhuān)業(yè)解釋?zhuān)?/p>

          這里我們用反證法來(lái)進(jìn)行解釋為何需要兩階段提交。由于 redo log 和 binlog 是兩個(gè)獨(dú)立的邏輯,如果不用兩階段提交,要么就是先寫(xiě)完 redo log 再寫(xiě) binlog,或者采用反過(guò)來(lái)的順序。我們看看這兩種方式會(huì)有什么問(wèn)題。

          仍然用前面的 update 語(yǔ)句來(lái)做例子。假設(shè)當(dāng)前 username = ‘陳哈哈’ 的行,賬戶(hù)余額字段 money 的值是 100,再假設(shè)執(zhí)行 update 語(yǔ)句過(guò)程中在寫(xiě)完第一個(gè)日志后,第二個(gè)日志還沒(méi)有寫(xiě)完期間發(fā)生了 crash(異常宕機(jī)),會(huì)出現(xiàn)什么情況呢?

          依舊以這條SQL為例:

          update T set money = 0 + 500 where username = '陳哈哈';

          1、先寫(xiě) redo log 后寫(xiě) binlog。

          假設(shè)在 redo log 寫(xiě)完,binlog 還沒(méi)有寫(xiě)完的時(shí)候,MySQL 進(jìn)程異常重啟。由于我們前面說(shuō)過(guò)的,redo log 寫(xiě)完之后,系統(tǒng)即使崩潰,仍然能夠把數(shù)據(jù)恢復(fù)回來(lái),所以恢復(fù)后這一行 money 的值是 money + 500。

          但是由于 binlog 沒(méi)寫(xiě)完就 crash 了,這時(shí)候 binlog 里面就沒(méi)有記錄這個(gè)語(yǔ)句。因此,之后備份日志的時(shí)候,存起來(lái)的 binlog 里面就沒(méi)有這條語(yǔ)句。

          然后你會(huì)發(fā)現(xiàn),如果需要用這個(gè) binlog 來(lái)恢復(fù)臨時(shí)庫(kù)的話(huà),由于這個(gè)語(yǔ)句的 binlog 丟失,這個(gè)臨時(shí)庫(kù)就會(huì)少了這一次更新,恢復(fù)出來(lái)的這一行 money 的值就是 0,與原庫(kù)的值不同。

          2、先寫(xiě) binlog 后寫(xiě) redo log。

          如果在 binlog 寫(xiě)完之后 crash,由于 redo log 還沒(méi)寫(xiě),崩潰恢復(fù)以后這個(gè)事務(wù)無(wú)效,用戶(hù)余額 money 的值應(yīng)當(dāng)是 0。

          但是 binlog 里面已經(jīng)記錄了“把 money 從 0 改成 500 這個(gè)日志。所以,在之后用 binlog 來(lái)恢復(fù)的時(shí)候就多了一個(gè)事務(wù)出來(lái),恢復(fù)出來(lái)的這一行 money 的值就是 500,與原庫(kù)的值不同。

          可以看到,如果不使用“兩階段提交”,那么數(shù)據(jù)庫(kù)的狀態(tài)就有可能和用它的日志恢復(fù)出來(lái)的庫(kù)的狀態(tài)不一致。

          簡(jiǎn)單說(shuō),redo log 和 binlog 都可以用于表示事務(wù)的提交狀態(tài),而兩階段提交就是讓這兩個(gè)狀態(tài)保持邏輯上的一致。

          日志落盤(pán)

          保證事務(wù)成功,日志必須落盤(pán),這樣,數(shù)據(jù)庫(kù)crash后,就不會(huì)丟失某個(gè)事務(wù)的數(shù)據(jù)了

          • innodb_flush_log_at_trx_commit 這個(gè)參數(shù)設(shè)置成 1 的時(shí)候,表示每次事務(wù)的 redo log 都直接持久化到磁盤(pán)。這樣可以保證 MySQL 異常重啟之后數(shù)據(jù)不丟失。
          • sync_binlog 這個(gè)參數(shù)設(shè)置成 1 的時(shí)候,表示每次事務(wù)的 binlog 都持久化到磁盤(pán)。這樣可以保證 MySQL 異常重啟之后 binlog 不丟失。
          面試官:(老臉一紅)

          面試官:小李,坦白說(shuō)我也很久沒(méi)搞技術(shù)了,但我覺(jué)得你確實(shí)很懂這塊兒,為什么?因?yàn)槟惆盐叶冀o我干困了。。我很欣賞你吹…講故事的能力,你,你懂我意思吧。

          面試官:小李啊,你等我一會(huì)兒。(馬經(jīng)理提著褲子走出了辦公室)

          熊貓:(尿遁了??不應(yīng)該啊,我這波操作難道還不香么?難道,被識(shí)破了??-_-’’|)

          五分鐘后HR來(lái)了。。

          HR:小李,我就說(shuō)你行吧!!領(lǐng)導(dǎo)很看好你,說(shuō)你表達(dá)思路奇特,很符合這個(gè)崗位,并給你點(diǎn)了個(gè)贊,讓我通知你下周來(lái)入職吧。

          熊貓:好的好的,看來(lái)現(xiàn)在開(kāi)發(fā)對(duì)表達(dá)能力要求還挺高啊~~

          HR:??兄弟不是應(yīng)聘產(chǎn)品么?

          熊貓:????????你跟我倆擱這兒扯犢子呢?我應(yīng)聘的軟件開(kāi)發(fā)工程師大哥?

          HR:(嗯,看來(lái)果然是我打錯(cuò)面試電話(huà)了。。冷靜冷靜,小問(wèn)題)

          HR:好的,那今天就先這樣,回去等通知吧???? 還有啥問(wèn)題要問(wèn)我么?

          熊貓:。。。。。

          總結(jié)

          好了,今天咱們了解了 MySQL 里面最重要的兩個(gè)日志,即物理日志 redo log 和邏輯日志 binlog。另外,MySQL 系列面試題和答案全部整理好了,微信搜索互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)發(fā)送:2T,可以在線(xiàn)閱讀。

          為該講的內(nèi)容總結(jié)了幾個(gè)問(wèn)題, 大家復(fù)習(xí)的時(shí)候可以先嘗試回答這些問(wèn)題檢查自己的掌握程度。

          1. redo log的概念是什么? 為什么會(huì)存在.

          2. 什么是WAL(write-ahead log)機(jī)制, 好處是什么.

          3. redo log 為什么可以保證crash safe機(jī)制.

          4. binlog的概念是什么, 起到什么作用, 可以做crash safe嗎?

          5. binlog和redolog的不同點(diǎn)有哪些?

          6. 物理一致性和邏輯一致性各應(yīng)該怎么理解?

          7. 執(zhí)行器和innoDB在執(zhí)行update語(yǔ)句時(shí)候的流程是什么樣的?

          8. 如果數(shù)據(jù)庫(kù)誤操作, 如何執(zhí)行數(shù)據(jù)恢復(fù)?

          9. 什么是兩階段提交, 為什么需要兩階段提交, 兩階段提交怎么保證數(shù)據(jù)庫(kù)中兩份日志間的邏輯一致性(什么叫邏輯一致性)?

          10. 如果不是兩階段提交, 先寫(xiě)redo log和先寫(xiě)bin log兩種情況各會(huì)遇到什么問(wèn)題?

          原文鏈接:https://blog.csdn.net/qq_39390545/article/details/115214802

          看完這篇文章,你有什么收獲?歡迎在留言區(qū)與10w+Java開(kāi)發(fā)者一起討論~

          最后,關(guān)注公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)回復(fù):2T,可以獲取我整理和創(chuàng)作的 Java 系列教程非常齊全。
           推薦閱讀 

          1、2019 年 9 月全國(guó)程序員工資統(tǒng)計(jì),你是什么水平?

          2、如何才能成為優(yōu)秀的架構(gòu)師?

          3、從零開(kāi)始搭建創(chuàng)業(yè)公司后臺(tái)技術(shù)棧

          4、程序員一般可以從什么平臺(tái)接私活?

          5、37歲程序員被裁,120天沒(méi)找到工作,無(wú)奈去小公司,結(jié)果懵了...

          6、滴滴業(yè)務(wù)中臺(tái)構(gòu)建實(shí)踐,首次曝光

          7、不認(rèn)命,從10年流水線(xiàn)工人,到谷歌上班的程序媛,一位湖南妹子的勵(lì)志故事

          8、15張圖看懂瞎忙和高效的區(qū)別!

          瀏覽 26
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美日韩一级视频 | 亚洲欧美视频免费观看 | 性爱9999 | 在线看黄片视频 | 国产精品综合激情 |