當(dāng)前位置:首頁 >  站長 >  數(shù)據(jù)庫 >  正文

Mysql臟頁flush及收縮表空間原理解析

 2020-11-16 11:37  來源: 腳本之家   我來投稿 撤稿糾錯(cuò)

  域名預(yù)訂/競價(jià),好“米”不錯(cuò)過

這篇文章主要介紹了Mysql臟頁flush及收縮表空間原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

mysql臟頁

由于WAL機(jī)制,InnoDB在更新語句的時(shí)候,制作了寫日志這一個(gè)磁盤操作,就是redo log,在內(nèi)存寫完redo log后,就返回給客戶端, 即更新成功。

把內(nèi)存里的數(shù)據(jù)寫入磁盤的過程,術(shù)語就是flush,在flush之前,實(shí)際數(shù)據(jù)和數(shù)據(jù)庫中的數(shù)據(jù)是不一致的,因?yàn)樵趓edo log基礎(chǔ)上更新了還未寫入,數(shù)據(jù)庫是老的,當(dāng)內(nèi)存數(shù)據(jù)頁跟磁盤數(shù)據(jù)頁內(nèi)容不一致的時(shí)候,稱這個(gè)內(nèi)存頁為臟頁,內(nèi)存寫入后就一致了,稱為干凈頁,

如果mysql偶爾運(yùn)行速度很慢,很可能是在刷臟頁。引發(fā)數(shù)據(jù)庫flush的過程

redo log滿了,系統(tǒng)停止所有更新操作,將checkpoint向前推進(jìn),騰出空間繼續(xù)寫。

系統(tǒng)內(nèi)存不足,需要新的內(nèi)存頁不夠用,就會淘汰一些數(shù)據(jù)頁,留給別的數(shù)據(jù)頁使用,如果淘汰的是臟頁,就會先寫到磁盤。

mysql空閑的時(shí)候。

正常關(guān)閉mysql的時(shí)候

在第一種情況下,redo log滿了,這種情況是innodb要避免的,因?yàn)檎麄€(gè)系統(tǒng)都不能再更新了,這是不能接受的

第二種情況,內(nèi)存滿了,要先寫到磁盤,innodb用緩沖池管理內(nèi)存,有三種狀態(tài)

還沒有用的內(nèi)存頁

用了并且是干凈頁

用了并且是臟頁(淘汰的時(shí)候需要寫入到磁盤)

所以我們有時(shí)使用數(shù)據(jù)庫會發(fā)現(xiàn)數(shù)據(jù)庫性能突然下降,可能就是在處理臟頁。

刷臟頁控制策略

Innodb_io_capacity參數(shù),這個(gè)參數(shù)會告訴innodb你的磁盤io能力。(有公式計(jì)算)

innodb刷盤主要兩個(gè)因素:臟頁比例和redo log的寫盤速度

innodb_max_derty_pages_pct是臟頁比例上限,默認(rèn)是75%,調(diào)整好Innodb_io_capacity參數(shù)值,使臟頁比例不要超過75%收縮表空間

場景例子:數(shù)據(jù)庫占用空間太大,把最大的表刪掉了一半數(shù)據(jù),表的大小還是沒有變化。

數(shù)據(jù)刪除流程

加入要?jiǎng)h掉R4,InnoDB引擎只會把R4這個(gè)記錄標(biāo)記為刪除,如果之后再摻入一個(gè)ID在300-600之間的記錄時(shí),會復(fù)用這個(gè)位置,但是磁盤文件的大小并不會縮小。

如果刪掉了一個(gè)數(shù)據(jù)頁上的所有記錄,這個(gè)數(shù)據(jù)頁就可以被復(fù)用。

注意:數(shù)據(jù)頁的復(fù)用跟記錄的復(fù)用是不同的。

比如R4這條記錄被刪除,如果插入一個(gè)ID是400的行,直接復(fù)用這個(gè)空間,但是如果插入ID是800的行,就不能復(fù)用這個(gè)位置了。

但是整個(gè)數(shù)據(jù)頁P(yáng)age A上的所有記錄刪除之后,pageA標(biāo)記為可復(fù)用,如果插入一條ID=50的記錄需要用新的數(shù)據(jù)頁的時(shí)候,PageA是可以背負(fù)用的。

如果我們用delete命令把整個(gè)表數(shù)據(jù)刪除,結(jié)果是所有的數(shù)據(jù)頁都會標(biāo)記為可復(fù)用,但是在磁盤上,文件不會變小。

插入數(shù)據(jù)流程

如果數(shù)據(jù)按照索引順序插入的,索引是緊湊的,但是如果是隨機(jī)插入的,就會造成索引的數(shù)據(jù)頁分頁。

如果pageA已經(jīng)滿了,在插入一行數(shù)據(jù)會怎樣?由于A滿了,在插入一個(gè)id是550的數(shù)據(jù)時(shí),就會申請一個(gè)新的頁面pageB來保存數(shù)據(jù),分裂完成后pageA的末尾就留下了空洞。

更新索引上的值也是刪除一個(gè)舊的值,再插入一個(gè)新值,也會造成空洞。

收縮空間

新建一個(gè)與表A相同結(jié)構(gòu)的表B,按照主鍵ID遞增的順序,把數(shù)據(jù)一行一行的從A里讀出來再插入到表B中,表B中無空洞,數(shù)據(jù)頁的利用率也更高,如果我們把表B作為臨時(shí)表,數(shù)據(jù)從表A導(dǎo)入到B中的操作完成后,用B替換A,從效果上也起到了收縮A的作用。

在整個(gè)DDL過程中,表A不能有更新,所以這個(gè)DDL不是online的,在5.6之后的版本中,流程做了更改:

建立一個(gè)臨時(shí)文件,掃描A中的所有數(shù)據(jù)頁,

用數(shù)據(jù)頁中A的記錄生成B+樹,存儲在臨時(shí)文件中

將所有對A的操作記錄在一個(gè)日志文件中

臨時(shí)文件生成后,將日志文件的操作應(yīng)用到臨時(shí)文件,得到一個(gè)邏輯數(shù)據(jù)上與表A相同的數(shù)據(jù)文件

用臨時(shí)文件替換表A的數(shù)據(jù)文件

可以看到,與圖3過程的不同之處在于,由于日志文件記錄和重放操作這個(gè)功能的存在,這個(gè)方案在重建表的過程中,允許對表A做增刪改操作。

使用alter table A engine=InnoDB命令來重建表。在MySQL 5.5版本之前,這個(gè)命令的執(zhí)行流程跟我們前面描述的差不多,區(qū)別只是這個(gè)臨時(shí)表B不需要你自己創(chuàng)建,MySQL會自動完成轉(zhuǎn)存數(shù)據(jù)、交換表名、刪除舊表的操作。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

來源:腳本之家

鏈接:https://www.jb51.net/article/195379.htm

申請創(chuàng)業(yè)報(bào)道,分享創(chuàng)業(yè)好點(diǎn)子。點(diǎn)擊此處,共同探討創(chuàng)業(yè)新機(jī)遇!

相關(guān)標(biāo)簽
mysql

相關(guān)文章

  • MySQL5.7 集群配置的步驟

    這篇文章主要介紹了MySQL5.7集群配置的步驟,幫助大家更好的理解和學(xué)習(xí)使用MySQL,感興趣的朋友可以了解下

    標(biāo)簽:
    mysql
  • MySQL中觸發(fā)器和游標(biāo)的介紹與使用

    這篇文章主要給大家介紹了關(guān)于MySQL中觸發(fā)器和游標(biāo)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

    標(biāo)簽:
    mysql
  • MySQL中exists、in及any的基本用法

    這篇文章主要給大家介紹了關(guān)于MySQL中exists、in及any的基本用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

    標(biāo)簽:
    mysql
  • MySQL正確修改最大連接數(shù)的3種方案

    這篇文章主要給大家介紹了關(guān)于MySQL正確修改最大連接數(shù)的3種方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

    標(biāo)簽:
    mysql
  • 教你怎么在Windows系統(tǒng)上手動搭建MySql數(shù)據(jù)庫

    1.已經(jīng)購買好的騰訊云輕量應(yīng)用服務(wù)器。2.作者本次演示使用的系統(tǒng)是WindowsServer2019,其他windows版本也可以,操作流程大同小異。3.使用Windows遠(yuǎn)程桌面連接騰訊云輕量服務(wù)器。

熱門排行

信息推薦