如何理解MySQL數(shù)據(jù)庫(kù)Innodb內(nèi)存結(jié)構(gòu)以及怎樣使用內(nèi)存的,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。
10余年的寧國(guó)網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。成都全網(wǎng)營(yíng)銷推廣的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整寧國(guó)建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。成都創(chuàng)新互聯(lián)公司從事“寧國(guó)網(wǎng)站設(shè)計(jì)”,“寧國(guó)網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
概述
很多朋友可能會(huì)有許多關(guān)于Innodb如何使用內(nèi)存的問(wèn)題。我這里將簡(jiǎn)單介紹一下innodb內(nèi)存結(jié)構(gòu),然后以innodb啟動(dòng)時(shí)的分配情況做一個(gè)解釋。
1. INNODB內(nèi)存結(jié)構(gòu)
(1) 聚集索引與非聚集索引:
聚集索引:主鍵,有序,存儲(chǔ)順序與內(nèi)存一致
非聚集索引:非主鍵,無(wú)序
聚集索引在葉子節(jié)點(diǎn)存儲(chǔ)的是表中的數(shù)據(jù)
非聚集索引在葉子節(jié)點(diǎn)存儲(chǔ)的是主鍵和索引列
使用非聚集索引查詢出數(shù)據(jù)時(shí),拿到葉子上的主鍵再去查到想要查找的數(shù)據(jù)。(拿到主鍵再查找這個(gè)過(guò)程叫做回表)
(2) 緩沖池:
緩沖池用于存放各種數(shù)據(jù)的緩存。Innodb總是將磁盤中的數(shù)據(jù)(數(shù)據(jù)庫(kù)文件)按頁(yè)(16K)讀取到緩沖池,然后按最近最少使用算法(LRU)來(lái)保存緩沖池中的數(shù)據(jù)。
如果數(shù)據(jù)庫(kù)文件需要修改,總是先修改在緩存池中的頁(yè)(發(fā)生修改后,該頁(yè)為臟頁(yè)),然后按一定頻率刷新到磁盤中。
(3) insert buffer(插入緩沖):
使用條件:1.索引是輔助索引;2.索引不是唯一的。
也就是說(shuō),主鍵索引不使用插入緩沖。主鍵索引是聚集索引,插入是順序的,執(zhí)行效率比較高,就不借助緩沖了。
但是,當(dāng)表中存在輔助索引(非聚集索引,非主鍵)時(shí),不一定是順序的了,這時(shí)需要離散的訪問(wèn),插入性能會(huì)降低。
所以,對(duì)于非聚集索引的插入和更新操作,不是直接插入到索引頁(yè)中,而是插入到緩沖中,再以一定頻率執(zhí)行插入緩沖和非聚集索引葉子節(jié)點(diǎn)的合并操作。
注:由于非主鍵索引葉子節(jié)點(diǎn)存的是主鍵和當(dāng)前列值,所以使用非聚集索引查詢時(shí),先查輔助索引的那顆樹(shù)找到對(duì)應(yīng)的主鍵,再查主鍵索引的那顆樹(shù),會(huì)查兩次,效率不高。
(4) redo log(重做日志):
在事務(wù)提交的時(shí)候,Innodb會(huì)先把數(shù)據(jù)從磁盤中讀到內(nèi)存進(jìn)行修改,然后把事務(wù)日志寫(xiě)到日志緩沖(log buffer),然后再刷新到重做日志文件(redo log file)中進(jìn)行持久化,然后再定期刷新到磁盤中。
用于在實(shí)例故障恢復(fù)時(shí),繼續(xù)那些已經(jīng)commit但數(shù)據(jù)尚未完全回寫(xiě)到磁盤的事務(wù)。
(5) double write(兩次寫(xiě)):
為防止redo log在寫(xiě)的過(guò)程中損壞,我們需要留個(gè)備份。若出現(xiàn)故障,先從備份中恢復(fù)redo log,再進(jìn)行數(shù)據(jù)恢復(fù)。
(6) undo log:
記錄數(shù)據(jù)修改前的鏡像,用于將未提交的事務(wù)回滾到事務(wù)開(kāi)始前的狀態(tài)。
undo操作:當(dāng)Innodb存儲(chǔ)引擎回滾時(shí),它實(shí)際上做的是與之前相關(guān)的工作,對(duì)于insert操作,Innodb會(huì)完成一個(gè)delete,對(duì)于update,則會(huì)執(zhí)行一個(gè)相反的update,將修改前的行放回去。
(7) 自適應(yīng)哈希索引:
Innodb會(huì)監(jiān)控表上索引的查找頻率,若發(fā)現(xiàn)建立哈希索引會(huì)提升速度,則自動(dòng)創(chuàng)建哈希索引。不是對(duì)整張表建立索引,而是根據(jù)訪問(wèn)頻率對(duì)某些頁(yè)建立。
(8) 事務(wù)提交:
事務(wù)進(jìn)行過(guò)程中,每次sql語(yǔ)句執(zhí)行,都會(huì)記錄undo log和redo log,然后更新數(shù)據(jù)形成臟頁(yè)。然后redo log按照時(shí)間或空間等條件進(jìn)行落盤,undo log和臟頁(yè)按照checkpoint進(jìn)行落盤,落盤后相應(yīng)的redo log就可以刪除了。
此時(shí),事務(wù)還未commit,如果發(fā)生崩潰,則首先檢查checkpoint記錄,使用相應(yīng)的redo log進(jìn)行數(shù)據(jù)和undo log的恢復(fù),然后查看undo log的狀態(tài)發(fā)現(xiàn)事務(wù)尚未提交,然后就使用undo log進(jìn)行回滾。事務(wù)執(zhí)行commit操作時(shí),會(huì)將本事務(wù)相關(guān)的所有redo log都進(jìn)行落盤,只有所有redo log落盤成功,才算commit成功。
然后內(nèi)存中的數(shù)據(jù)臟頁(yè)繼續(xù)按照checkpoint進(jìn)行落盤。如果此時(shí)發(fā)生了崩潰,則只使用redo log恢復(fù)數(shù)據(jù)。
2. 一些重要的概念:
NBLOCKS=Innodb_buffer_pool有多個(gè)頁(yè)(block)=innodb_buffer_pool_size/16384(16k)
OS_THREADS= if ( innodb_buffer_pool_size >= 1000Mb) = 50000
else if (innodb_buffer_pool_size >= 8Mb) = 10000
else = 1000 (該值只用在*nixes系統(tǒng)上,對(duì)于Windows有一點(diǎn)小的區(qū)別計(jì)算OS_THREADS)
3. Innodb 使用的內(nèi)存包括:
innodb_buffer_pool_size
innodb_additional_mem_pool_size
innodb_log_buffer_size
adaptive index hash ,size (innodb buffer 索引管理區(qū))= innodb_buffer_pool_size/64
system dictionary hash,size(innodb內(nèi)部字典區(qū)) = 6 * innodb_buffer_pool_size/512
memory for sync_array,size(用于Innodb內(nèi)部syncronzation的開(kāi)銷)=OS_THREAD * 512
memory for os_event,size(用于innodb內(nèi)存的syncronzation的開(kāi)銷)=OS_THREAD * 216
memory for locking system(內(nèi)存的鎖管理系統(tǒng)),size = 5 * 4 *NBBLOCKS
4. innodb內(nèi)存使用的計(jì)算公式為:
Innodb_buffer_pool_size + innodb_log_buffer_size + innodb_additional_mem_pool_size + 812/16384 * innodb_buffer_pool_size + OS_THREADS * 368
對(duì)于812/16384 * Innodb_buffer_pool_size 可以簡(jiǎn)單的用 innodb_buffer_pool_size / 20 計(jì)算,對(duì)于OS_THREADS * 368
OS_THREADS * 368 = 17.5 MB if innodb_buffer_pool_size > 1000MB OS_THREADS * 3368 = 3.5 MB if innodb_buffer_pool_size > 8MB
舉一個(gè)例子:
如果你的innodb_buffer_pool_size有1500MB,innodb_additional_mem_pool_size =20 MB,innodb_log_buffer_size = 8M,
Innodb 將會(huì)向系統(tǒng)申請(qǐng)內(nèi)存為= 1500M + 20M + 8M + 1500/20 M +17.5 = 1620.5M
根據(jù)以上的條件可以算出Innodb最根本最需要多少內(nèi)存,這樣對(duì)于服務(wù)器的內(nèi)存使用也可以有一個(gè)規(guī)劃了。
關(guān)于如何理解MySQL數(shù)據(jù)庫(kù)Innodb內(nèi)存結(jié)構(gòu)以及怎樣使用內(nèi)存的問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。