MySQL進(jìn)階二(InnoDB存儲(chǔ)引擎)

大綱

  1. 存儲(chǔ)引擎介紹
  2. MySQL架構(gòu)與內(nèi)部模塊
  3. innoDB的磁盤(pán)結(jié)構(gòu)與內(nèi)存結(jié)構(gòu)

繼續(xù)上一篇鹰溜,我們?cè)诘玫綀?zhí)行計(jì)劃之后,sql是不是就可以執(zhí)行了行贪?這里有兩個(gè)問(wèn)題:
1.數(shù)據(jù)存放在哪里牵咙?或者說(shuō)放在一個(gè)什么結(jié)構(gòu)里面
2.執(zhí)行計(jì)劃在哪里執(zhí)行,怎么執(zhí)行萄金?

1.存儲(chǔ)引擎的基本介紹

我們先來(lái)看第一個(gè)問(wèn)題蟀悦,在關(guān)系型數(shù)據(jù)庫(kù)中,數(shù)據(jù)是存放在表中氧敢,我們可以把這個(gè)表理解成Excel里面的表格日戈,所以我們?cè)诖鎯?chǔ)數(shù)據(jù)時(shí)還要組織數(shù)據(jù)的存儲(chǔ)結(jié)構(gòu),這個(gè)存儲(chǔ)結(jié)構(gòu)就是由我們的存儲(chǔ)引擎決定的孙乖,在MySQL里面浙炼,支持多種存儲(chǔ)引擎份氧,存儲(chǔ)引擎是以插件的形式存在,那么這些存儲(chǔ)引擎的差別在哪里呢弯屈?

1.1存儲(chǔ)引擎比較

常見(jiàn)的存儲(chǔ)引擎
??innoDB和MyISAM是我們用的最多的兩個(gè)存儲(chǔ)引擎蜗帜,在MySQL5.5之前,默認(rèn)的存儲(chǔ)引擎是MyISAM资厉,它是MySQL自帶的厅缺。
??MyISAM前身是ISAM(Indexed Sequential Access Method:利用索引,順序存取數(shù)據(jù)的方法)酌住。
??MySQL5.5之后默認(rèn)的存儲(chǔ)引擎改成了innoDB店归,主要是因?yàn)镮nnoDB支持事務(wù),支持行級(jí)鎖酪我,對(duì)于業(yè)務(wù)一致性的要求高的場(chǎng)景來(lái)說(shuō)更合適消痛。


如果需要一個(gè)用于查詢(xún)的臨時(shí)表,可以用memory都哭,顧名思義就是存在于內(nèi)存中的表秩伞,訪問(wèn)速度會(huì)很快。
具體各個(gè)存儲(chǔ)引擎的特性:https://dev.mysql.com/doc/refman/5.7/en/storage-engines.html

1.2.執(zhí)行引擎

第二個(gè)問(wèn)題欺矫,執(zhí)行計(jì)劃就是由執(zhí)行引擎去操作存儲(chǔ)引擎的纱新,不同的存儲(chǔ)引擎實(shí)現(xiàn)了相同的API,因此對(duì)于執(zhí)行引擎來(lái)說(shuō)穆趴,不同的存儲(chǔ)引擎的操作是一樣的脸爱。

2.MySQL體系架構(gòu)總結(jié)
2.1模塊詳解

Connectors:用來(lái)支持各種語(yǔ)言和SQL的交互,比如PHP未妹,Java等簿废。
management Service&utililties:系統(tǒng)管理和控制工具,包括備份恢復(fù)络它,MySQL復(fù)制族檬,集群等。
connection pool:連接池化戳,管理需要緩沖的資源单料,包括用戶(hù)密碼權(quán)限線程等。
sql interface:用來(lái)接收客戶(hù)端的sql命令点楼,并返回結(jié)果扫尖。
parser:用來(lái)解析sql語(yǔ)句。
optimizer:查詢(xún)優(yōu)化器掠廓。
cache & buffers:查詢(xún)緩存藏斩,還有表緩存,key緩存却盘,權(quán)限緩存等狰域。
pluggable storage engines:插件式存儲(chǔ)引擎媳拴,提供api給服務(wù)層使用。

2.2架構(gòu)分層
3.一條更新SQL是如何執(zhí)行的兆览?

基本流程和查詢(xún)SQL是一致的屈溉,解析器-》優(yōu)化器-》執(zhí)行引擎,主要的區(qū)別在于拿到符合條件的數(shù)據(jù)之后的操作抬探。

3.1緩沖池 Buffer Pool

??首先子巾,innoDB的數(shù)據(jù)都是存儲(chǔ)在磁盤(pán)中的,innoDB操作數(shù)據(jù)有一個(gè)最小單元小压,叫做頁(yè)(索引頁(yè)和數(shù)據(jù)頁(yè))线梗。我們對(duì)數(shù)據(jù)的操作,不是每次都直接操作磁盤(pán)怠益,這樣太慢了仪搔。innnoDB使用了一種緩沖池的技術(shù),也即是把磁盤(pán)讀到的每一頁(yè)放到一塊內(nèi)存里面蜻牢,這個(gè)區(qū)域就叫做Buffer Pool烤咧。
??每次讀取頁(yè)的時(shí)候,先從緩存池中讀取抢呆,如果緩存池中存在就直接讀取煮嫌,不再訪問(wèn)磁盤(pán)。
??修改數(shù)據(jù)的時(shí)候抱虐,先修改緩存池里的頁(yè)昌阿。當(dāng)磁盤(pán)和緩存池里的頁(yè)數(shù)據(jù)不一致的時(shí)候,我們把它叫做臟頁(yè)恳邀。InnoDB會(huì)有專(zhuān)門(mén)的線程懦冰,把buffer pool的數(shù)據(jù)寫(xiě)入到磁盤(pán),每隔一段時(shí)間就把多個(gè)修改寫(xiě)入磁盤(pán)轩娶,這個(gè)動(dòng)作就叫刷臟儿奶。

3.2.InnoDB的內(nèi)存和磁盤(pán)結(jié)構(gòu):https://dev.mysql.com/doc/refman/5.7/en/innodb-architecture.html
InnoDB Architecture
3.2.1.內(nèi)存結(jié)構(gòu)

1. Buffer Pool
?Buffer Pool緩存的是頁(yè)信息框往,包括索引頁(yè)和數(shù)據(jù)頁(yè)鳄抒,默認(rèn)大小是128M(134217728字節(jié)),可以調(diào)整椰弊。當(dāng)緩存池滿(mǎn)了的時(shí)候许溅,使用LRU算法來(lái)管理緩存池(鏈表實(shí)現(xiàn),不是傳統(tǒng)的LRU秉版,分成了young和old)贤重,經(jīng)過(guò)淘汰的數(shù)據(jù)之后剩下的就是熱點(diǎn)數(shù)據(jù)。
2. change Buffer 寫(xiě)緩存
??在更新緩存的時(shí)候清焕,如果在緩存中沒(méi)有數(shù)據(jù)并蝗,就要從磁盤(pán)讀取一次數(shù)據(jù)到緩存再更新祭犯,至少會(huì)發(fā)生一次io,所以為了避免這種情況滚停,增加了一塊change Buffer沃粗,如果這個(gè)數(shù)據(jù)頁(yè)不是唯一索引,不需要考慮數(shù)據(jù)唯一性(否則就還是要跟磁盤(pán)的數(shù)據(jù)作比較键畴,避免不了io操作)最盅,這種情況下可以先把修改記錄在緩沖池中,從而提升語(yǔ)句(insert update delete)的執(zhí)行速度起惕。最后把Change Buffer 記錄到數(shù)據(jù)頁(yè)的操作叫merge涡贱,什么時(shí)候發(fā)生merge:在訪問(wèn)這個(gè)數(shù)據(jù)頁(yè)的時(shí)候、或者通過(guò)后臺(tái)線程惹想、或者數(shù)據(jù)庫(kù)shut down问词、redo log寫(xiě)滿(mǎn)時(shí)觸發(fā)。
??如果數(shù)據(jù)大部分索引時(shí)非唯一索引勺馆,并且業(yè)務(wù)時(shí)寫(xiě)多讀少戏售,不會(huì)在數(shù)據(jù)寫(xiě)后立即讀取,就可以調(diào)大一點(diǎn)Change Buffer草穆,默認(rèn)是占Buffer Pool的25%灌灾。
3.Log Buffer(redo Log)
??如果buffer pool的臟頁(yè)還沒(méi)有刷新到磁盤(pán)時(shí),數(shù)據(jù)庫(kù)宕機(jī)或者重啟悲柱,這些數(shù)據(jù)丟失锋喜。如果寫(xiě)到一半,甚至?xí)茐臄?shù)據(jù)文件導(dǎo)致數(shù)據(jù)不可用豌鸡。為了避免這個(gè)問(wèn)題嘿般,innoDB把所有的寫(xiě)操作專(zhuān)門(mén)寫(xiě)入到一個(gè)日志文件,并且在數(shù)據(jù)庫(kù)啟動(dòng)時(shí)從這個(gè)文件進(jìn)行恢復(fù)操作(實(shí)現(xiàn)crash-safe)-用來(lái)實(shí)現(xiàn)事務(wù)的持久性涯冠。
??這個(gè)文件就是磁盤(pán)的redo Log炉奴,對(duì)應(yīng)于/var/lib/mysql/目錄下的ib_logfile0和ib_logfile1,每個(gè)大小48M
??這種日志和磁盤(pán)的配合過(guò)程蛇更,其實(shí)就是MySQL里面的WAL(Write Ahead Log)瞻赶,先寫(xiě)日志,再寫(xiě)磁盤(pán)派任。
??這里還有個(gè)知識(shí)點(diǎn)砸逊,寫(xiě)redo Log到磁盤(pán)是順序IO,寫(xiě)數(shù)據(jù)到磁盤(pán)是隨機(jī)io掌逛,所以寫(xiě)日志的速度更快师逸。
??redo log buffer寫(xiě)入到磁盤(pán)的時(shí)機(jī)有3種選擇,首先我們知道豆混,內(nèi)存往磁盤(pán)寫(xiě)數(shù)據(jù)中間時(shí)存在操作系統(tǒng)緩存的篓像,flush就是把os cache刷到磁盤(pán)中动知。
show variables like 'innodb_flush_log_trx_commit'
默認(rèn)是1,含義:https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit



總結(jié)一下redo Log的特點(diǎn):

  1. redo Log是innoDB存儲(chǔ)引擎實(shí)現(xiàn)的员辩,不是所有存儲(chǔ)引擎都有實(shí)現(xiàn)
  2. redo Log記錄的是物理日志拍柒,不是記錄每一行數(shù)據(jù)改了之后的狀態(tài),是記錄數(shù)據(jù)頁(yè)的改動(dòng)屈暗。
  3. redo Log的大小是固定的拆讯,前面寫(xiě)的內(nèi)容會(huì)被覆蓋。


    圖片.png

    checkpoint是當(dāng)前要覆蓋的位置养叛。如果writepos跟checkpoint重疊种呐,說(shuō)明redo
    log已經(jīng)寫(xiě)滿(mǎn),這時(shí)候需要同步redo log到磁盤(pán)中弃甥。

3.2.2.磁盤(pán)結(jié)構(gòu)

??表空間可以看作是innoDB存儲(chǔ)引擎邏輯層最高層爽室,所有的數(shù)據(jù)都存放在表空間中。InnoDB的表空間分為5大類(lèi)淆攻。
系統(tǒng)表空間 system table space
??主要包含雙寫(xiě)緩沖阔墩,change buffer,undo log瓶珊,如果沒(méi)有指定file-per-table啸箫,也會(huì)包含用戶(hù)創(chuàng)建的表。

  1. undo log(撤銷(xiāo)日志或回滾日志)記錄了事務(wù)發(fā)生之前的數(shù)據(jù)狀態(tài)伞芹。
    如果修改數(shù)據(jù)時(shí)出現(xiàn)異常忘苛,可以用undo log來(lái)實(shí)現(xiàn)回滾操作(保持原子性)。
    在執(zhí)行undo 的時(shí)候唱较,僅僅是將數(shù)據(jù)從邏輯上恢復(fù)至事務(wù)之前的狀態(tài)扎唾,而不是從物理頁(yè)面上操作實(shí)現(xiàn)的,屬于邏輯格式的日志南缓。
    redo Log和undo Log與事務(wù)密切相關(guān)胸遇,統(tǒng)稱(chēng)為事務(wù)日志。
  2. 數(shù)據(jù)字典:由內(nèi)部系統(tǒng)表組成汉形,存儲(chǔ)表和索引的元數(shù)據(jù)(定義信息)纸镊。
  3. 雙寫(xiě)緩沖(InnoDB的一大特性):
    InnoDB的頁(yè)和操作系統(tǒng)的頁(yè)大小不一致,InnoDB頁(yè)大小一般為16K获雕,操作系統(tǒng)頁(yè)大小為4K薄腻,InnoDB的頁(yè)寫(xiě)入到磁盤(pán)時(shí)收捣,一個(gè)頁(yè)需要分4次寫(xiě)届案。

    如果存儲(chǔ)引擎正在寫(xiě)入頁(yè)的數(shù)據(jù)到磁盤(pán)時(shí)發(fā)生了宕機(jī),可能出現(xiàn)頁(yè)只寫(xiě)了一部分的情況罢艾,比如只寫(xiě)了4K楣颠,就宕機(jī)了尽纽,這種情況叫做部分寫(xiě)失效(partialpagewrite),可能會(huì)導(dǎo)致數(shù)據(jù)丟失童漩。盡管我們已經(jīng)有了redo log但是如果這個(gè)頁(yè)已經(jīng)損壞弄贿,那再恢復(fù)也是沒(méi)意義的,因此我們應(yīng)用redo log之前需要一個(gè)頁(yè)的副本矫膨,如果出現(xiàn)了頁(yè)的寫(xiě)入失效差凹,則先還原這個(gè)頁(yè)再應(yīng)用redo log。這個(gè)頁(yè)的副本就是double write侧馅,雙寫(xiě)技術(shù)危尿,通過(guò)它保證數(shù)據(jù)頁(yè)的可靠性。
    有了這些日志之后馁痴,我們來(lái)總結(jié)一下一個(gè)更新操作的流程谊娇,這是一個(gè)簡(jiǎn)化的過(guò)程。
    name原值是qingshan罗晕。
    updateusersetname='penyuyan'whereid=1;
    1济欢、事務(wù)開(kāi)始,從內(nèi)存或磁盤(pán)取到這條數(shù)據(jù)小渊,返回給Server 的執(zhí)行器法褥;
    2、執(zhí)行器修改這一行數(shù)據(jù)的值為penyuyan酬屉;
    3挖胃、記錄name=qingshan到undo log;
    4梆惯、記錄name=penyuyan到redo log酱鸭;
    5、調(diào)用存儲(chǔ)引擎接口垛吗,在內(nèi)存(Buffer Pool)中修改 name=penyuyan凹髓;
    6、事務(wù)提交怯屉。
3.3.Binlog日志

??binlog以事件的形式記錄了所有的DDL和DML語(yǔ)句(因?yàn)樗涗浀氖遣僮鞫皇菙?shù)據(jù)值蔚舀,屬于邏輯日志),可以用來(lái)做主從復(fù)制和數(shù)據(jù)恢復(fù)锨络。
??跟redo log不一樣赌躺,它的文件內(nèi)容是可以追加的,沒(méi)有固定大小限制羡儿。
??在開(kāi)啟了binlog功能的情況下礼患,我們可以把binlog導(dǎo)出成SQL語(yǔ)句,把所有的操作重放一遍,來(lái)實(shí)現(xiàn)數(shù)據(jù)的恢復(fù)缅叠。
??binlog的另一個(gè)功能就是用來(lái)實(shí)現(xiàn)主從復(fù)制悄泥,它的原理就是從服務(wù)器讀取主服務(wù)器的binlog,然后執(zhí)行一遍肤粱。
有了這兩個(gè)日志之后弹囚,我們來(lái)看一下一條更新語(yǔ)句是怎么執(zhí)行的:


整體流程

1、先查詢(xún)到這條數(shù)據(jù)领曼,如果有緩存鸥鹉,也會(huì)用到緩存。
2庶骄、把name改成盆魚(yú)宴宋舷,然后調(diào)用引擎的API接口,寫(xiě)入這一行數(shù)據(jù)到內(nèi)存瓢姻,同時(shí)記錄redo log祝蝠。這時(shí) redo log 進(jìn)入prepare 狀態(tài),然后告訴執(zhí)行器幻碱,執(zhí)行完成了绎狭,可以隨時(shí)提交。
3褥傍、 執(zhí)行器收到通知后記錄binlog儡嘶,然后調(diào)用存儲(chǔ)引擎接口, 設(shè)置redolog為commit狀態(tài)恍风。
4蹦狂、更新完成净捅。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末看政,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子娶牌,更是在濱河造成了極大的恐慌锦募,老刑警劉巖摆屯,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異糠亩,居然都是意外死亡虐骑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)赎线,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)廷没,“玉大人,你說(shuō)我怎么就攤上這事垂寥〉呃瑁” “怎么了另锋?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)盏缤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蓖扑,這世上最難降的妖魔是什么唉铜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮律杠,結(jié)果婚禮上潭流,老公的妹妹穿的比我還像新娘。我一直安慰自己柜去,他們只是感情好灰嫉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著嗓奢,像睡著了一般讼撒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上股耽,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天根盒,我揣著相機(jī)與錄音,去河邊找鬼物蝙。 笑死炎滞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诬乞。 我是一名探鬼主播册赛,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼震嫉!你這毒婦竟也來(lái)了森瘪?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤票堵,失蹤者是張志新(化名)和其女友劉穎柜砾,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體换衬,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡痰驱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瞳浦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片担映。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖叫潦,靈堂內(nèi)的尸體忽然破棺而出蝇完,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布短蜕,位于F島的核電站氢架,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏朋魔。R本人自食惡果不足惜岖研,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望警检。 院中可真熱鬧孙援,春花似錦、人聲如沸扇雕。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)镶奉。三九已至础淤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哨苛,已是汗流浹背值骇。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留移国,地道東北人吱瘩。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像迹缀,于是被迫代替她去往敵國(guó)和親使碾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容