本篇內(nèi)容介紹了“InnoDB的內(nèi)存結(jié)構(gòu)及特性”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
創(chuàng)新互聯(lián)是一家專業(yè)提供長(zhǎng)順企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、H5場(chǎng)景定制、小程序制作等業(yè)務(wù)。10年已為長(zhǎng)順眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站設(shè)計(jì)公司優(yōu)惠進(jìn)行中。
?InnoDB存儲(chǔ)引擎支持事務(wù),其設(shè)計(jì)目標(biāo)主要面向在線事務(wù)處理(OLTP)的應(yīng)用。其特點(diǎn)是行鎖設(shè)計(jì)、支持外鍵,并支持非鎖定讀,即默認(rèn)讀操作不會(huì)產(chǎn)生鎖。
InnoDB通過使用多版本并發(fā)控制(MVCC)來獲取高并發(fā)性,并且實(shí)現(xiàn)了SQL標(biāo)準(zhǔn)的4中隔離級(jí)別,默認(rèn)為REPEATABLE級(jí)別。同時(shí),使用一種被稱為next-key-locking的策略來避免幻讀現(xiàn)象的產(chǎn)生。除此之外,InnoDB存儲(chǔ)引擎還提供了插入緩沖(insert buffer)、二次寫(double write)、自適應(yīng)哈希索引(adaptive hash index)、預(yù)讀(read ahead)等高性能和高可用的功能。
?InnoDB存儲(chǔ)引擎是基于磁盤存儲(chǔ)的,并將其中的記錄按照頁的方式進(jìn)行管理。但是由于CPU速度和磁盤速度之間的鴻溝,基于磁盤的數(shù)據(jù)庫系統(tǒng)通常使用緩沖池記錄來提高數(shù)據(jù)庫的的整體性能。
?在數(shù)據(jù)庫中進(jìn)行讀取操作,首先將從磁盤中讀到的頁放在緩沖池中,下次再讀相同的頁中時(shí),首先判斷該頁是否在緩沖池中。若在緩沖池中,稱該頁在緩沖池中被命中,直接讀取該頁。否則,讀取磁盤上的頁。
?對(duì)于數(shù)據(jù)庫中頁的修改操作,則首先修改在緩沖池中的頁,然后再以一定的頻率刷新到磁盤上。頁從緩沖池刷新回磁盤的操作并不是在每次頁發(fā)生更新時(shí)觸發(fā),而是通過一種稱為CheckPoint的機(jī)制刷新回磁盤。
?所以,緩沖池的大小直接影響著數(shù)據(jù)庫的整體性能,可以通過配置參數(shù)innodb_buffer_pool_size來設(shè)置。
?具體來看,緩沖池中緩存的數(shù)據(jù)頁類型有:索引頁、數(shù)據(jù)頁、undo頁、插入緩沖(insert buffer)、自適應(yīng)哈希索引(adaptive hash index)、InnoDB存儲(chǔ)的鎖信息(lock info)和數(shù)據(jù)字典信息(data dictionary)。
?在架構(gòu)圖上可以看到,InnoDB存儲(chǔ)引擎的內(nèi)存區(qū)域除了有緩沖池之外,還有重做日志緩沖和額外內(nèi)存池。InnoDB存儲(chǔ)引擎首先將重做日志信息先放到這個(gè)緩沖區(qū)中,然后按照一定頻率將其刷新到重做日志文件中。重做日志緩沖一般不需要設(shè)置的很大,該值可由配置參數(shù)innodb_log_buffer_size控制。
?Page是Innodb存儲(chǔ)的最基本結(jié)構(gòu),也是Innodb磁盤管理的最小單位,與數(shù)據(jù)庫相關(guān)的所有內(nèi)容都存儲(chǔ)在Page結(jié)構(gòu)里。Page分為幾種類型,數(shù)據(jù)頁和索引頁就是其中最為重要的兩種類型。
?我們都知道,在InnoDB引擎上進(jìn)行插入操作時(shí),一般需要按照主鍵順序進(jìn)行插入,這樣才能獲得較高的插入性能。當(dāng)一張表中存在非聚簇的且不唯一的索引時(shí),在插入時(shí),數(shù)據(jù)頁的存放還是按照主鍵進(jìn)行順序存放,但是對(duì)于非聚簇索引葉節(jié)點(diǎn)的插入不再是順序的了,這時(shí)就需要離散的訪問非聚簇索引頁,由于隨機(jī)讀取的存在導(dǎo)致插入操作性能下降。
?InnoDB為此設(shè)計(jì)了Insert Buffer來進(jìn)行插入優(yōu)化。對(duì)于非聚簇索引的插入或者更新操作,不是每一次都直接插入到索引頁中,而是先判斷插入的非聚集索引是否在緩沖池中,若在,則直接插入;若不在,則先放入到一個(gè)Insert Buffer中??此茢?shù)據(jù)庫這個(gè)非聚集的索引已經(jīng)查到葉節(jié)點(diǎn),而實(shí)際沒有,這時(shí)存放在另外一個(gè)位置。然后再以一定的頻率和情況進(jìn)行Insert Buffer和非聚簇索引頁子節(jié)點(diǎn)的合并操作。這時(shí)通常能夠?qū)⒍鄠€(gè)插入合并到一個(gè)操作中,這樣就大大提高了對(duì)于非聚簇索引的插入性能。
?如果說Insert Buffer給InnoDB存儲(chǔ)引擎帶來了性能上的提升,那么Double Write帶給InnoDB存儲(chǔ)引擎的是數(shù)據(jù)頁的可靠性。
?如上圖所示,Double Write由兩部分組成,一部分是內(nèi)存中的double write buffer,大小為2MB,另一部分是物理磁盤上共享表空間連續(xù)的128個(gè)頁,大小也為2MB。在對(duì)緩沖池的臟頁進(jìn)行刷新時(shí),并不直接寫磁盤,而是通過memcpy函數(shù)將臟頁先復(fù)制到內(nèi)存中的該區(qū)域,之后通過doublewrite buffer再分兩次,每次1MB順序地寫入共享表空間的物理磁盤上,然后馬上調(diào)用fsync函數(shù),同步磁盤,避免操作系統(tǒng)緩沖寫帶來的問題。在完成doublewrite頁的寫入后,再講doublewirite buffer中的頁寫入各個(gè)表空間文件中。
?如果操作系統(tǒng)在將頁寫入磁盤的過程中發(fā)生了崩潰,在恢復(fù)過程中,InnoDB存儲(chǔ)引擎可以從共享表空間中的doublewrite中找到該頁的一個(gè)副本,將其復(fù)制到表空間文件中,再應(yīng)用重做日志。
?當(dāng)緩沖池中的頁的版本比磁盤要新時(shí),數(shù)據(jù)庫需要將新版本的頁從緩沖池刷新到磁盤。但是如果每次一個(gè)頁發(fā)送變化,就進(jìn)行刷新,那么性能開發(fā)是非常大的,于是InnoDB采用了Write Ahead Log策略,即當(dāng)事務(wù)提交時(shí),先寫重做日志,然后再擇時(shí)將臟頁寫入磁盤。如果發(fā)生宕機(jī)導(dǎo)致數(shù)據(jù)丟失,就通過重做日志進(jìn)行數(shù)據(jù)恢復(fù)。
?InnoDB存儲(chǔ)引擎會(huì)首先將重做日志信息先放入重做日志緩沖中,然后再按照一定頻率將其刷新到重做日志文件。重做日志緩沖一般不需要設(shè)置得很大,因?yàn)橐话闱闆r每一秒鐘都會(huì)講重做日志緩沖刷新到日志文件中??赏ㄟ^配置參數(shù)innodb_log_buffer_size控制,默認(rèn)為8MB。
?除了每秒刷新機(jī)制之外,每次事務(wù)提交時(shí)重做日志緩沖也會(huì)刷新到日志中。InnoDB是事務(wù)的存儲(chǔ)引擎,其通過Force Log at Commit機(jī)制實(shí)現(xiàn)事務(wù)的持久性,即當(dāng)事務(wù)提交時(shí),必須先將該事務(wù)的所有日志寫入到重做日志文件進(jìn)行持久化,然后事務(wù)的提交操作完成才算完成。InnoDB的寫入機(jī)制大致入下圖所示。
?為了確保每次日志都寫入到重做日志文件,在每次講重做日志緩沖寫入重做日志后,必須調(diào)用一次fsync操作,將緩沖文件從文件系統(tǒng)緩存中真正寫入磁盤。
?可以通過innodb_flush_log_at_trx_commit來控制重做日志刷新到磁盤的策略。該參數(shù)默認(rèn)值為1,表示事務(wù)提交必須進(jìn)行一次fsync操作,還可以設(shè)置為0和2。0表示事務(wù)提交時(shí)不進(jìn)行寫入重做日志操作,該操作只在主線程中完成,2表示提交時(shí)寫入重做日志,但是只寫入文件系統(tǒng)緩存,不進(jìn)行fsync操作。由此可見,設(shè)置為0時(shí),性能最高,但是喪失了事務(wù)的一致性。
?InnoDB會(huì)根據(jù)訪問的頻率和模式,為熱點(diǎn)頁建立哈希索引,來提高查詢效率。InnoDB存儲(chǔ)引擎會(huì)監(jiān)控對(duì)表上各個(gè)索引頁的查詢,如果觀察到建立哈希索引可以帶來速度上的提升,則建立哈希索引,所以叫做自適應(yīng)哈希索引。
?自適應(yīng)哈希索引是通過緩沖池的B+樹頁構(gòu)建而來,因此建立速度很快,而且不需要對(duì)整張數(shù)據(jù)表建立哈希索引。其有一個(gè)要求,即對(duì)這個(gè)頁的連續(xù)訪問模式必須是一樣的,也就是說其查詢的條件(WHERE)必須完全一樣,而且必須是連續(xù)的。
?我們都知道,InnoDB存儲(chǔ)引擎會(huì)在行級(jí)別上對(duì)表數(shù)據(jù)進(jìn)行上鎖。不過InnoDB也會(huì)在數(shù)據(jù)庫內(nèi)部其他很多地方使用鎖,從而允許對(duì)多種不同資源提供并發(fā)訪問。數(shù)據(jù)庫系統(tǒng)使用鎖是為了支持對(duì)共享資源進(jìn)行并發(fā)訪問,提供數(shù)據(jù)的完整性和一致性。關(guān)于鎖的具體知識(shí)我們之后再進(jìn)行詳細(xì)學(xué)習(xí)。
?InnoDB有自己的表緩存,可以稱為表定義緩存或者數(shù)據(jù)字典。當(dāng)InnoDB打開一張表,就增加一個(gè)對(duì)應(yīng)的對(duì)象到數(shù)據(jù)字典。
?數(shù)據(jù)字典是對(duì)數(shù)據(jù)庫中的數(shù)據(jù)、庫對(duì)象、表對(duì)象等的元信息的集合。在MySQL中,數(shù)據(jù)字典信息內(nèi)容就包括表結(jié)構(gòu)、數(shù)據(jù)庫名或表名、字段的數(shù)據(jù)類型、視圖、索引、表字段信息、存儲(chǔ)過程、觸發(fā)器等內(nèi)容。MySQL INFORMATION_SCHEMA庫提供了對(duì)數(shù)據(jù)局元數(shù)據(jù)、統(tǒng)計(jì)信息、以及有關(guān)MySQL server的訪問信息(例如:數(shù)據(jù)庫名或表名,字段的數(shù)據(jù)類型和訪問權(quán)限等)。該庫中保存的信息也可以稱為MySQL的數(shù)據(jù)字典。
“InnoDB的內(nèi)存結(jié)構(gòu)及特性”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!