本文主要給大家介紹InnoDB存儲(chǔ)引擎概念的整體概括,其所涉及的東西,從理論知識(shí)來(lái)獲悉,有很多書(shū)籍、文獻(xiàn)可供大家參考,從現(xiàn)實(shí)意義角度出發(fā),創(chuàng)新互聯(lián)累計(jì)多年的實(shí)踐經(jīng)驗(yàn)可分享給大家。
成都創(chuàng)新互聯(lián)長(zhǎng)期為成百上千客戶(hù)提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為大同企業(yè)提供專(zhuān)業(yè)的網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作,大同網(wǎng)站改版等技術(shù)服務(wù)。擁有10年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。
MySQL對(duì)應(yīng)InnoDB版本
MySQL 5.1》InnoDB 1.0.X
MySQL 5.5》InnoDB 1.1.X
MySQL 5.6》InnoDB 1.2.X
后臺(tái)線程
1.Master Thread
負(fù)責(zé)將緩沖池中的數(shù)據(jù)異步刷新到磁盤(pán),保證數(shù)據(jù)的一致性;包括刷新臟頁(yè)、合并插入緩沖、undo頁(yè)的回收。
2.IO Thread
innodb存儲(chǔ)引擎中大量使用了AIO(Async IO)來(lái)處理寫(xiě)IO請(qǐng)求來(lái)提高數(shù)據(jù)庫(kù)的并發(fā)性能,共有四類(lèi)IO線程,分別是:insert buffer thread、log thread、read thread、write thread。其中read thread和write thread分別有四個(gè)線程,可以通過(guò)innodb_read_io_threads和innodb_write_io_threads來(lái)配置。
SHOW VARIABLES LIKE 'innodb_%io_threads'或者 SHOW ENGINE INNODB STATUS \G;
3.Purge Thread線程
purge Thread線程用來(lái)回收事務(wù)提交后其被分配的undo頁(yè),默認(rèn)是開(kāi)啟的,可以通過(guò)innodb_purge_threads=1配置多個(gè)Purge Thread線程。
show variables like 'innodb_purge_threads'; 配置2個(gè)Purge thread,只能修改配置文件配置,不能在線修改 innodb_purge_threads=2
4.Page Cleaner Thread
用于多版本控制功能中回收delete和update操作產(chǎn)生的臟頁(yè),用來(lái)執(zhí)行將臟頁(yè)刷新到磁盤(pán)。
5.Binlog Dump線程
當(dāng)配置了復(fù)制后,會(huì)在主云服務(wù)器生成一個(gè)binlog Dump線程來(lái)讀取二進(jìn)制修改記錄。
6.lock線程
用于鎖控制和死鎖檢測(cè)
內(nèi)存
不要理解以為內(nèi)存中就只有innodb buffer,還包括重做日志緩沖、額外的內(nèi)存池(目前還不知道比如join buffer、order buffer、key buffer、table cache buffer等是在緩沖池內(nèi)部還是獨(dú)立于緩沖池在內(nèi)存中)
1.緩存池
緩存的數(shù)據(jù)主要有數(shù)據(jù)頁(yè)、索引頁(yè)、重做日志頁(yè)(undolog)、節(jié)點(diǎn)信息、系統(tǒng)數(shù)據(jù)、插入緩沖、自適應(yīng)哈希索引、數(shù)據(jù)字典、鎖信息等
查看緩沖池的大小,單位字節(jié),轉(zhuǎn)化為MB需要/1024/1024 show variables like 'innodb_buffer_pool_size'; 默認(rèn)innodb有8個(gè)緩沖池,可以通過(guò)配置innodb_buffer_pool_instances 查詢(xún) show engine innodb status \G; 或者 SELECT * FROM information_schema.innodb_buffer_pool_status;
讀操作:
數(shù)據(jù)是以頁(yè)為存儲(chǔ)單位,在緩沖池中緩存了很多數(shù)據(jù)頁(yè),當(dāng)?shù)谝淮巫x取時(shí)首先將頁(yè)從磁盤(pán)讀取到緩存池中,當(dāng)下一次再去讀相同的數(shù)據(jù)頁(yè)時(shí)如果該也在緩存池中就直接從緩沖池中讀取而不需要再去磁盤(pán)讀,最理想的方式是將所有的磁盤(pán)數(shù)據(jù)都緩存到緩沖池中但是這得內(nèi)存足夠大才行。
修改操作
innodb存儲(chǔ)引擎對(duì)數(shù)據(jù)的修改也是先修改緩沖池中的數(shù)據(jù)頁(yè)(如果存在),然后根據(jù)一定的頻率刷新到磁盤(pán)來(lái)修改數(shù)據(jù)文件,這涉及到checkpoint機(jī)制,
插入操作(insert buffer)
因?yàn)閿?shù)據(jù)是按照聚集索引的順序排列的,所有針對(duì)聚集索引的插入一般會(huì)非???,而非聚集索引的插入就不一定是順序的,這個(gè)時(shí)候需要離散的訪問(wèn)非聚集索引頁(yè),插入的性能往往會(huì)很差,有一種情況可能例外就是非聚集索引的時(shí)間字段,而時(shí)間往往是順序的,這種情況會(huì)比較快,針對(duì)非聚集索引的這種情況就引入了插入緩沖。
innodb中引入了插入緩沖(insert buffer),insert buffer只針不唯一的非聚集索引,對(duì)于非聚集索引的插入和更新操作不是每次直接插入到索引文件中,而是先判斷插入的非聚集索引頁(yè)是否存在緩沖池中,如果存在則直接插入緩沖池的非聚集索引文件中,否則先放入到一個(gè)insert buffer對(duì)象當(dāng)中,但是給人的感覺(jué)它已經(jīng)插入到了索引文件中,但是實(shí)際并沒(méi)有,然后再以一定的頻率插入到索引文件當(dāng)中,在這個(gè)過(guò)程中如果存在多個(gè)相同的索引頁(yè)的插入會(huì)合并插入,大大的提高了非聚集索引的插入性能,
因?yàn)槊看尾迦胧窍炔迦氲骄彌_池當(dāng)中不去查找索引頁(yè)來(lái)判斷記錄的唯一性,因?yàn)槿プ雠袛嘈枰ルx散查找,所以插入緩沖不針對(duì)唯一性的非聚集索引。
在密集寫(xiě)操作的情況下,插入緩沖會(huì)占用過(guò)多的緩沖池的內(nèi)存,默認(rèn)最大可以占到50%,源代碼中的IBUF_POOL_SIZE_PER_MAX_SIZE=2,如果將其修改為3,則最大只能使用1/3的緩沖池的內(nèi)存。
2.LRU List、Free List、Flush List
innodb緩沖池中的頁(yè)默認(rèn)大小為16KB,緩沖池通過(guò)LRU(Latest Recent Used 最新少使用)算法來(lái)進(jìn)行管理,將最頻繁的使用的頁(yè)放在LRU列表的前端,而最近少使用的頁(yè)放在尾端,當(dāng)緩存池中的空間不足的時(shí)會(huì)先刪除尾端的頁(yè)來(lái)釋放空間。LRU有一個(gè)midpoint位置,默認(rèn)在LRU的37%的位置,左邊表示old列表,右邊表示new列表(熱點(diǎn)數(shù)據(jù)),新插入緩沖池中的頁(yè)先放在midpoint的位置,如果新插入的頁(yè)一來(lái)就移動(dòng)到new列表的話可能會(huì)導(dǎo)致new列表中的某些活動(dòng)也被移除到old列表中,比如表掃描操作一次性可能需要訪問(wèn)很多的數(shù)據(jù)頁(yè)而這些數(shù)據(jù)頁(yè)可能以后很少被使用,新插入的頁(yè)何時(shí)才會(huì)被被放入new列表中呢,為了解決這個(gè)問(wèn)題innodb引入了innodb_old_blocks_time參數(shù),該參數(shù)用來(lái)控制新插入的數(shù)據(jù)頁(yè)在mid位置多久后才被加入到new列表中。
查看midpoint的位置,如果覺(jué)得熱點(diǎn)數(shù)據(jù)空間需要更多可以將該值設(shè)小 show variables like 'innodb_old_blocks_pct' 查詢(xún)innodb_old_blocks_time值,單位毫秒,默認(rèn)是1000毫秒即1秒 show variables like 'innodb_old_blocks_time'
查看緩沖池中所有頁(yè)的信息,包括空閑頁(yè),所有的數(shù)據(jù)頁(yè)*16KB其實(shí)也就是緩沖池的總大小.select * from information_schema.INNODB_BUFFER_PAGE; 查看LUR列表的信息,包括new list和old list但是不包括free list,表中的字段記錄了當(dāng)前的數(shù)據(jù)頁(yè)的信息,包括緩沖池ID,頁(yè)的類(lèi)型(數(shù)據(jù)頁(yè)、索引頁(yè)、undo log、other),表名,索引名,是否是old list的頁(yè),是否屬于壓縮頁(yè)(可以將原本16K的頁(yè)壓縮為1K、2K、4K、8K),壓縮頁(yè)的大小,是否屬于臟頁(yè)。select POOL_ID,LRU_POSITION,SPACE,PAGE_TYPE,FLUSH_TYPE,NEWEST_MODIFICATION,OLDEST_MODIFICATION,INDEX_NAME,DATA_SIZE,COMPRESSED_SIZE,COMPRESSED,IS_OLD from information_schema.INNODB_BUFFER_PAGE_LRU;
OLDEST_MODIFICATION>0表示臟頁(yè)的數(shù)量也就是(modified db pages) IS_OLD='YES'代表OLD List頁(yè) COMPRESSED<>0代表壓縮頁(yè)
flush list:值的就是LRU中的臟頁(yè),flust list存在于New List中,即OLDEST_MODIFICATION>0(modified db pages)
3.日志緩沖(log buffer):對(duì)應(yīng)innodb日志文件
查看重做日志緩沖 show variables like 'innodb_log_buffer_size%';
InnoDB存儲(chǔ)引擎首先將重做日志信息先放入到重做日志緩沖中,然后按照一定的頻率將其刷新到重做日志文件當(dāng)中。默認(rèn)緩沖大小是8M,8M基本可以滿(mǎn)足需求,不需要配置太大的重做日志緩沖。
刷新機(jī)制:
1.Master Thread 每一秒將重做日志緩沖刷新到重做日志文件;
2.每個(gè)事務(wù)提交時(shí)會(huì)將重做日志緩沖刷新到重做日志文件;
3.當(dāng)重做日志緩沖池剩余空間小于1/2時(shí)
注意:innodb_log_buffer_size的大小應(yīng)該要比最大的事務(wù)大小要打,否則事務(wù)還未提交innodb_log_buffer_size就已經(jīng)寫(xiě)滿(mǎn)就需要進(jìn)行刷新操作,會(huì)造成一個(gè)事務(wù)需要多次進(jìn)行磁盤(pán)日志刷新操作,導(dǎo)致效率低。
4.額外的內(nèi)存
平時(shí)我們的服務(wù)器MySQL進(jìn)程所使用的內(nèi)存會(huì)比配置的InnoDB緩沖池的內(nèi)存要大,那是因?yàn)镸ySQL除了緩沖池中緩存的內(nèi)存額外還需要一部分內(nèi)存用來(lái)控制緩沖池內(nèi)部的一些資源信息,比如LRU、鎖資源、等待等。
CheckPoint機(jī)制
為了解決CPU和磁盤(pán)直接速度的問(wèn)題采用了緩沖池,所以對(duì)數(shù)據(jù)的操作都是先在緩沖池中完成,緩沖池中的數(shù)據(jù)頁(yè)往往比磁盤(pán)上的數(shù)據(jù)頁(yè)要新,我們將在緩沖池中已經(jīng)修改但是還未應(yīng)用到磁盤(pán)的數(shù)據(jù)頁(yè)叫“臟頁(yè)”,數(shù)據(jù)頁(yè)最終還是需要更新到磁盤(pán)中,中間會(huì)涉及到CheckPoint機(jī)制。
同時(shí)為了解決因?yàn)橥蝗环?wù)器停機(jī)導(dǎo)致緩沖池中還未來(lái)得及刷新到磁盤(pán)的臟頁(yè)丟失的問(wèn)題,加入了重做日志文件(重做日志文件默認(rèn)是配置2個(gè),默認(rèn)名稱(chēng)是ib_logfile開(kāi)頭,重做日志文件默認(rèn)大小是48M,兩個(gè)重做日志文件采取循環(huán)寫(xiě)的方式),當(dāng)事務(wù)提交時(shí)先寫(xiě)重做日志,當(dāng)發(fā)生服務(wù)器停機(jī)后可以通過(guò)重做日志來(lái)完成恢復(fù)(服務(wù)器重啟之后自己默認(rèn)會(huì)恢復(fù)),所以得保證重做日志文件有剩余空間,默認(rèn)機(jī)制是當(dāng)重做日志文件空間達(dá)到75%-90%時(shí)就刷新一部分臟頁(yè)到磁盤(pán)同時(shí)清空對(duì)應(yīng)的重做日志空間。
每次刷新多少頁(yè)到磁盤(pán):
Sharp Checkpoint:數(shù)據(jù)庫(kù)關(guān)閉時(shí)將所有臟頁(yè)都刷新回磁盤(pán),默認(rèn)方式,參數(shù):innodb_fast_shutdown=1
Fuzzy Checkpoint:刷新部分臟頁(yè),具體分為以下四種情況
1.Master Thread Checkpoint
Master Thread每隔幾秒鐘從緩沖池中將臟頁(yè)刷新回磁盤(pán)
2.FLUSH_LRU_LIST CheckPoint
在5.6版本之后需要保證LRU默認(rèn)存在1024個(gè)可用頁(yè),如果可用頁(yè)不足1024頁(yè)刷新部分臟頁(yè)回磁盤(pán),通過(guò)參數(shù)“innodb_lru_scan_dapth”配置。
3.Async/Sync Flush Checkpoint
指的是因?yàn)橹刈鋈罩疚募臻g不足導(dǎo)致的同步或異步刷新臟頁(yè)回磁盤(pán),當(dāng)重做日志空間已使用的空間達(dá)到75%-90%就觸發(fā)異步刷新,如果超過(guò)90%就觸發(fā)同步刷新,一般不會(huì)觸發(fā)同步刷新操作,除非重做日志文件太小并且進(jìn)行LOAD DATA的BULK INSERT操作。
4.Dirty Page too much
保證緩沖池中臟頁(yè)的比例,當(dāng)緩沖池中的臟頁(yè)比例達(dá)到75%時(shí)就觸發(fā)刷新臟頁(yè)操作,通過(guò)參數(shù)“innodb_max_dirty_pages_pct”配置。
看了以上InnoDB存儲(chǔ)引擎概念的整體概括介紹,希望能給大家在實(shí)際運(yùn)用中帶來(lái)一定的幫助。本文由于篇幅有限,難免會(huì)有不足和需要補(bǔ)充的地方,大家可以繼續(xù)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊板塊,會(huì)定期給大家更新行業(yè)新聞和知識(shí),如有需要更加專(zhuān)業(yè)的解答,可在官網(wǎng)聯(lián)系我們的24小時(shí)售前售后,隨時(shí)幫您解答問(wèn)題的。