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

          表妹問(wèn)我innodb的引擎是怎么設(shè)計(jì)的

          共 4654字,需瀏覽 10分鐘

           ·

          2021-11-18 13:04


          hello大家好 我是大家的學(xué)習(xí)成長(zhǎng)小伙伴Captain



          面試官:平時(shí)用的數(shù)據(jù)庫(kù)有哪些呢


          表妹:親愛(ài)的面試官你好,我平時(shí)用的最多的數(shù)據(jù)庫(kù)就是mysql了,除此之外,還用過(guò)oracle、MongoDB、hbase,緩存redis以及數(shù)據(jù)倉(cāng)庫(kù)hive


          面試官:不錯(cuò),會(huì)的不少,今天我們只聊聊你最常用的mysql,應(yīng)該也是你最熟悉的吧


          表妹:理論上來(lái)說(shuō)是這個(gè)樣子,你先問(wèn)個(gè)問(wèn)題試試,我看看答不答的上來(lái)啦


          面試官也很豪爽:可以,那你給我說(shuō)一下innodb引擎是怎么設(shè)計(jì)的吧


          表妹:... ... 那個(gè)面試官,我突然想起來(lái)今天早上出門(mén)的時(shí)候,家里的煮蛋器上還煮著好幾個(gè)雞蛋呢,我得趕緊撈出來(lái)去,不然我怕雞蛋的皮給煮沒(méi)了


          面試官:好的,趕緊去吧,下次來(lái)面試的時(shí)候記得給我?guī)б粋€(gè)雞蛋


          玩歸玩,鬧歸鬧,別拿面試官開(kāi)玩笑


          開(kāi)玩笑,不要緊,沮喪出大門(mén)待通知


          表妹回到家淚汪汪,直接沖到我的屋子來(lái)質(zhì)問(wèn)我,為什么你上次給我說(shuō)沒(méi)有mysql的知識(shí)點(diǎn)的時(shí)候,沒(méi)有告訴我面面試官會(huì)問(wèn)這么霸道的問(wèn)題呢


          表妹:我把索引啊、B+樹(shù)啊啥的都準(zhǔn)備了,結(jié)果她問(wèn)我innodb怎么設(shè)計(jì)的,這我怎么知道的,他怎么不去問(wèn)mysql的設(shè)計(jì)師去啊


          我:沒(méi)關(guān)系,真正的勇士敢于面對(duì)慘烈的人生,我來(lái)帶著你分析分析,下次保證你能和面試官愉快的溝通,不用再編理由回家來(lái)?yè)齐u蛋了


          嗚嗚嗚嗚...



          開(kāi)題


          首先呢,我們先普及一下,mysql是一個(gè)關(guān)系型數(shù)據(jù)庫(kù),而數(shù)據(jù)庫(kù)的重點(diǎn)就是存儲(chǔ)數(shù)據(jù),這個(gè)引擎的作用就是如何來(lái)把這個(gè)數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù)服務(wù)器的硬盤(pán)上,存儲(chǔ)的什么結(jié)構(gòu),靠什么策略存儲(chǔ)


          如果每次都存儲(chǔ)直接保存到硬盤(pán),那是不是會(huì)導(dǎo)致速度很慢,我們可以先把數(shù)據(jù)保存到服務(wù)器的內(nèi)存中,再通過(guò)一定的持久化規(guī)則存儲(chǔ)到硬盤(pán)上,那么問(wèn)題來(lái)了,到底是多少條數(shù)據(jù)保存一次呢,還是幾分鐘一次呢,這些都是屬于策略問(wèn)題


          mysql結(jié)構(gòu)



          我們可以看到mysql的結(jié)構(gòu),來(lái)簡(jiǎn)單說(shuō)一下流程


          客戶(hù)端連接器:這個(gè)就是和各個(gè)編程語(yǔ)言進(jìn)行交互連接的,JDBC應(yīng)該是大家最熟悉的了吧


          系統(tǒng)管理和控制工具:進(jìn)行mysql中的元數(shù)據(jù)、備份、還有配置信息這種的系統(tǒng)管理和控制工具


          連接池:管理用戶(hù)的連接、線程處理這些需要緩存的數(shù)據(jù)


          SQL接口:接受SQL語(yǔ)句,返回查詢(xún)結(jié)果


          解析器:進(jìn)行SQL的解析,分解SQL語(yǔ)句,驗(yàn)證SQL合法性


          查詢(xún)優(yōu)化器:解析之后進(jìn)行查詢(xún)優(yōu)化,分析出最優(yōu)解的執(zhí)行計(jì)劃,注意,這里是最優(yōu)執(zhí)行計(jì)劃,但是并不一定代表是速度最快的執(zhí)行計(jì)劃


          緩存:查詢(xún)緩存,查詢(xún)的時(shí)候先去查詢(xún)緩存看是否命中緩存,如果命中則直接取數(shù)據(jù),屬于一個(gè)優(yōu)化


          可插拔存儲(chǔ)引擎:這個(gè)就是屬于我們這一篇要關(guān)注的,多種存儲(chǔ)引擎,對(duì)應(yīng)著不同的存儲(chǔ)機(jī)制,不同的事務(wù)和鎖機(jī)制等,innodb是其中的一個(gè)引擎,也是用的最多的引擎


          文件和日志:存儲(chǔ)到硬盤(pán)中的數(shù)據(jù)文件和日志文件,日志就是典型的那些binlog、redo log、undo log這些日志文件


          innodb的結(jié)構(gòu)



          接著我們看innodb的引擎的設(shè)計(jì)


          innodb主要可以分為兩大塊:In-Memory Structures內(nèi)存結(jié)構(gòu)和On-Disk Structures磁盤(pán)結(jié)構(gòu)


          innodb使用的屬于內(nèi)存和日志先行的一種策略,就是會(huì)把修改的數(shù)據(jù)先存儲(chǔ)到內(nèi)存中,然后將事務(wù)記錄保存到redo log日志文件中,這個(gè)日志文件就是用來(lái)保證數(shù)據(jù)庫(kù)事務(wù)中的持久化這個(gè)特性的


          先寫(xiě)到內(nèi)存和日志,再通過(guò)一定的策略將數(shù)據(jù)進(jìn)行持久化,只要將數(shù)據(jù)修改在內(nèi)存中完成和記錄在日志之后,對(duì)應(yīng)的事務(wù)就會(huì)返回給用戶(hù),表示該事務(wù)已經(jīng)完成了。但是實(shí)際上這個(gè)數(shù)據(jù)是還沒(méi)刷到硬盤(pán)中的


          也就是實(shí)際上可能會(huì)存在部分?jǐn)?shù)據(jù)丟失,innodb通過(guò)redo?log日志來(lái)保證數(shù)據(jù)的一致性,如果保證所有的重做日志,也就可以在系統(tǒng)崩潰的時(shí)候通過(guò)日志來(lái)進(jìn)行數(shù)據(jù)的恢復(fù)


          innodb還引入了檢查點(diǎn)機(jī)制,即定期檢查,保證檢查點(diǎn)之前的日志都已經(jīng)寫(xiě)到了磁盤(pán)中,則下次恢復(fù)只需要從檢查點(diǎn)開(kāi)始即可


          In-Memory Structures內(nèi)存結(jié)構(gòu)


          主要包含Buffer Pool、Change Buffer、Adaptive Hash Index和Log Buffer這四部分組成,然后從內(nèi)存結(jié)構(gòu)也可以看出來(lái),Change Buffer和Adaptive Hash Index占用的內(nèi)存也是屬于Buffer Pool中的,而Log?Buffer占用的內(nèi)存和Buffer Pool的內(nèi)存是相互獨(dú)立的



          Buffer?Pool

          The buffer pool is an area in main memory where InnoDB caches table and index data as it is accessed.

          我們?cè)谏厦嬉舱f(shuō)過(guò),mysql為了加速數(shù)據(jù)的查詢(xún)是做了很多的優(yōu)化的,這個(gè)就是其中一點(diǎn),mysql更新數(shù)據(jù)的時(shí)候并不會(huì)直接去修改磁盤(pán)中的數(shù)據(jù),這樣做是很影響效率的,每次都往硬盤(pán)中寫(xiě)數(shù)據(jù)肯定是不適合現(xiàn)在這種互聯(lián)網(wǎng)時(shí)代


          mysql先修改內(nèi)存,再記錄到redo log中,然后再根據(jù)相應(yīng)的策略將數(shù)據(jù)更新到硬盤(pán)中


          而這些數(shù)據(jù)的存放地方就是Buffer Pool


          大家在平時(shí)的開(kāi)發(fā)中肯定也使用過(guò)緩存,甭管是Redis還是Memcached,都是我們用于系統(tǒng)中的加速策略,查詢(xún)一個(gè)數(shù)據(jù)先去緩存中看一圈是否有,有的話直接把數(shù)據(jù)返回即可,沒(méi)有的話我們才會(huì)去數(shù)據(jù)庫(kù)中進(jìn)行查詢(xún)


          在現(xiàn)在這種系統(tǒng)中,我們都會(huì)把系統(tǒng)的一些熱點(diǎn)數(shù)據(jù)或者是訪問(wèn)量比較高的數(shù)據(jù)存儲(chǔ)到redis中,防止每次都查數(shù)據(jù)庫(kù)造成數(shù)據(jù)庫(kù)的壓力劇增


          在使用緩存的過(guò)程中,我們也要注意緩存血崩、緩存穿透和擊穿這些問(wèn)題,其實(shí)只要我們做好了防護(hù),這些問(wèn)題還是都比較好避免的,不太清楚的小伙伴可以去看我的redis篇


          哦對(duì)了,我的后續(xù)的文章都會(huì)及時(shí)更新到我的GitHub地址上 https://github.com/DayuMM2021/Java


          mysql是以頁(yè)為單位從磁盤(pán)中讀取數(shù)據(jù)的,而B(niǎo)uffer Pool也是這樣的,Buffer?Pool的數(shù)據(jù)是一個(gè)以頁(yè)為單位的鏈表


          那Buffer Pool自然不是無(wú)限大的,自然就需要相應(yīng)的淘汰策略,來(lái)進(jìn)行數(shù)據(jù)的清楚


          緩存池的使用情況可以通過(guò)show engine innodb status命令來(lái)查看,其中的一些主要信息


          ----------------------BUFFER POOL AND MEMORY----------------------Total large memory allocated 137428992 # 分配給InnoDB緩存池的內(nèi)存(字節(jié))Dictionary memory allocated 102398  # 分配給InnoDB數(shù)據(jù)字典的內(nèi)存(字節(jié))Buffer pool size   8191 # 緩存池的頁(yè)數(shù)目Free buffers       7893 # 緩存池空閑鏈表的頁(yè)數(shù)目Database pages     298  # 緩存池LRU鏈表的頁(yè)數(shù)目Modified db pages  0    # 修改過(guò)的頁(yè)數(shù)目......


          Change Buffer


          上面我們說(shuō)了Buffer Pool主要是用于優(yōu)化查詢(xún)速度的,那么如果我們要修改數(shù)據(jù)呢,要是每次更新都直接更新到磁盤(pán)中,這樣肯定是很慢的


          甚至如果更新的數(shù)據(jù)在磁盤(pán)中的頁(yè)是無(wú)規(guī)則的,那每次都需要把數(shù)據(jù)更新到不同的頁(yè)中,會(huì)大大的影響速度


          Change Buffer就是用于這個(gè)的,mysql如果發(fā)現(xiàn)你要修改的數(shù)據(jù)不在Buffer Pool中,就把你要修改的數(shù)據(jù)先記錄到Change Pool中,同時(shí)記錄到redo log日志中,然后再把這一頁(yè)的數(shù)據(jù)load到內(nèi)存中


          load到內(nèi)存之后,會(huì)把Change Buffer里面的記錄進(jìn)行修改,應(yīng)用到內(nèi)存Change Buffer中,這個(gè)動(dòng)作叫做merge


          接著把內(nèi)存數(shù)據(jù)刷到磁盤(pán)中,這個(gè)動(dòng)作叫做purge




          查看Change Buffer 信息也可以通過(guò) show engine innodb status 命令。


          merge:Change Buffer - Buffer Pool


          purge:Buffer Pool -?磁盤(pán)


          Adaptive Hash Index


          哈希索引我們知道是查詢(xún)速度很快的,缺點(diǎn)是不擅長(zhǎng)進(jìn)行范圍查詢(xún),我們一般使用的索引都是B+樹(shù),而B(niǎo)+樹(shù)的查詢(xún)速度則取決于樹(shù)的高度了


          不論數(shù)據(jù)在磁盤(pán)中,還是load到內(nèi)存中的數(shù)據(jù),存儲(chǔ)結(jié)構(gòu)都是B+樹(shù),我數(shù)據(jù)都已經(jīng)放到Buffer Pool中了,還得通過(guò)B+樹(shù)的多次IO才能查找到數(shù)據(jù),有些繁瑣


          于是自適應(yīng)哈希索引就來(lái)了,對(duì)于那些經(jīng)常被訪問(wèn)的數(shù)據(jù),不需要每次來(lái)了之后都走B+樹(shù)的多次查詢(xún)了,直接把數(shù)據(jù)的指針位置記錄下來(lái)即可


          自適應(yīng),我們是無(wú)法干預(yù)的,mysql自動(dòng)評(píng)估是否適合使用這個(gè)自適應(yīng)哈希索引,如果合適,則會(huì)建立數(shù)據(jù)的自適應(yīng)哈希索引


          Log Buffer


          重做日志redo log中的緩沖區(qū),大小默認(rèn)16M,由innodb_log_buffer_size定義,一個(gè)比較大的log buffer可以讓大的事務(wù)在提交前不必將日志中途刷到磁盤(pán)中,也可以提高效率


          如果系統(tǒng)中涉及到很多的大事務(wù),可以適當(dāng)?shù)募哟笤撝?/span>


          On-Disk Structures磁盤(pán)結(jié)構(gòu)


          這個(gè)屬于操作系統(tǒng)提升性能,在磁盤(pán)前面加的一層高速緩存


          表空間分為系統(tǒng)表空間、臨時(shí)表空間、常規(guī)表空間、Undo表空間和file-per-table表空間


          系統(tǒng)表空間又包括了InnoDB數(shù)據(jù)字典、雙寫(xiě)緩沖區(qū)Doublewrite Buffer、修改緩存和Undo日志等


          Redo日志存儲(chǔ)的就是Log Buffer刷到磁盤(pán)里的數(shù)據(jù)


          系統(tǒng)表空間


          包含內(nèi)容有數(shù)據(jù)字典,雙寫(xiě)緩沖,修改緩沖以及undo日志,以及在系統(tǒng)表空間創(chuàng)建的表的數(shù)據(jù)和索引。


          常規(guī)表空間


          類(lèi)似系統(tǒng)表空間,也是一種共享的表空間,可以通過(guò) CREATE TABLESPACE 創(chuàng)建常規(guī)表空間,多個(gè)表可共享一個(gè)常規(guī)表空間,也可以修改表的表空間。


          注意:必須刪除常規(guī)表空間中的表后才能刪除常規(guī)表空間。


          File-Per-Table表空間


          MySQL InnoDB新版本提供了 innodb_file_per_table 選項(xiàng),每個(gè)表可以有單獨(dú)的表空間數(shù)據(jù)文件(.ibd),而不是全部放到系統(tǒng)表空間數(shù)據(jù)文件 ibdata1 中。


          其他表空間


          其他表空間中Undo表空間存儲(chǔ)的是Undo日志。


          除了存儲(chǔ)在系統(tǒng)表空間外,Undo日志也可以存儲(chǔ)在單獨(dú)的Undo表空間中。


          臨時(shí)表空間則是非壓縮的臨時(shí)表的存儲(chǔ)空間,默認(rèn)是數(shù)據(jù)目錄的 ibtmp1 文件,所有臨時(shí)表共享,壓縮的臨時(shí)表用的是 File-Per-Table 表空間


          ??結(jié)束語(yǔ)


          Captain希望有一天能夠靠寫(xiě)作養(yǎng)活自己,現(xiàn)在還在磨練,這個(gè)時(shí)間可能會(huì)持續(xù)很久,但是,請(qǐng)看我漂亮的堅(jiān)持


          感謝大家能夠做我最初的讀者和傳播者,請(qǐng)大家相信,只要你給我一份愛(ài),我終究會(huì)還你們一頁(yè)情的。


          Captain會(huì)持續(xù)更新技術(shù)文章,和生活中的暴躁文章,歡迎大家關(guān)注【Java賊船】,成為船長(zhǎng)的學(xué)習(xí)小伙伴,和船長(zhǎng)一起乘千里風(fēng)、破萬(wàn)里浪


          哦對(duì)了,后續(xù)所有的文章都會(huì)更新到這里


          https://github.com/DayuMM2021/Java








          瀏覽 52
          點(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>
                  大香蕉之人妻 | 久久国产精品久久 | 国产婬片一级A片AAA毛片AⅤ | 日本极品无码巨乳在线播放视频 | 无码影音 |