MySQL InnoDB 技術(shù)內(nèi)幕

第一章 MySQL 體系架構(gòu)和存儲(chǔ)引擎

mysql是數(shù)據(jù)庫(kù)也是數(shù)據(jù)庫(kù)實(shí)例

mysql ?是一個(gè)單進(jìn)程多線(xiàn)程架構(gòu)的數(shù)據(jù)庫(kù) ?daemon 守護(hù)進(jìn)程

當(dāng)啟動(dòng)實(shí)例時(shí)搂赋,MySQL數(shù)據(jù)庫(kù)會(huì)去讀取配置文件瞧捌,根據(jù)配置文件的參數(shù)來(lái)啟動(dòng)數(shù)據(jù)庫(kù)實(shí)例完箩。

用以下命令可以查看當(dāng)Mysql 數(shù)據(jù)庫(kù)實(shí)例啟動(dòng)時(shí)粘捎,會(huì)在哪些位置查找配置文件帖蔓。

mysql —help | grep my.cnf


mysql由一下幾部分組成:

連接池組件

管理服務(wù)和工具組件

sql接口組件

查詢(xún)分析器組件

優(yōu)化器組件

緩沖(cache)組件

插件式存儲(chǔ)引擎

物理文件


最大的特點(diǎn)就是其插件式的表存儲(chǔ)引擎檬贰。存儲(chǔ)引擎是基于表的,而不是數(shù)據(jù)庫(kù)遵湖。

mysql獨(dú)有的插件式體系架構(gòu)悔政,存儲(chǔ)引擎的是mysql區(qū)別于其他數(shù)據(jù)庫(kù)的一個(gè)重要的特性。存儲(chǔ)引擎的好處是奄侠,每個(gè)存儲(chǔ)引擎都有各自的特點(diǎn)卓箫,能夠根據(jù)具體的應(yīng)用建立不同存儲(chǔ)引擎表。

MySql 存儲(chǔ)引擎的改進(jìn)http:/code.google.com.p/mysql-heap-dynamic-rows/

MySQL 數(shù)據(jù)庫(kù)開(kāi)源特性垄潮,存儲(chǔ)引擎可以分為MySql官方存儲(chǔ)引擎和第三方存儲(chǔ)引擎烹卒。Inno存儲(chǔ)引擎,是mysql 數(shù)據(jù)庫(kù)OLTP(online transaction Processing在線(xiàn)事務(wù)處理)應(yīng)用中使用最廣泛的存儲(chǔ)引擎弯洗。

1.3.1 ?InnoDB存儲(chǔ)引擎

InnoDB存儲(chǔ)引擎支持事務(wù)旅急,其設(shè)計(jì)目標(biāo)主要面向在線(xiàn)事務(wù)OLTP的應(yīng)用。其特點(diǎn)是行級(jí)鎖設(shè)計(jì)牡整、支持外鍵藐吮,并支持類(lèi)似于Oracle的非鎖定讀,從5.5.8開(kāi)始InnoDB存儲(chǔ)引擎是默認(rèn)的存儲(chǔ)引擎逃贝。

InnoDB通過(guò)使用多版本并發(fā)控制MVCC來(lái)獲得高并發(fā)性谣辞,并且實(shí)現(xiàn)了SQL標(biāo)準(zhǔn)的四種隔離級(jí)別,默認(rèn)的為REPEATABLE級(jí)別沐扳,同時(shí)使用一種被稱(chēng)為next-key locking的策略來(lái)避免幻讀(phantom)現(xiàn)象的產(chǎn)生泥从。除此之外,InnoDB存儲(chǔ)引擎還提供了插入緩沖(Insert buffer)沪摄、二次寫(xiě)(double write)躯嫉、自適應(yīng)哈希索引(adaptive hash index)、預(yù)讀(read ahead)等高性能和高可用的功能杨拐。

對(duì)于表中的數(shù)據(jù)存儲(chǔ)祈餐,InnoDB存儲(chǔ)引擎采用聚集(cluster)的方式,因此每張表的存儲(chǔ)都是按主鍵的順序進(jìn)行存放哄陶。如果沒(méi)有顯式地在表定義時(shí)指定主鍵帆阳,InnoDB存儲(chǔ)引擎會(huì)為每一行生成一個(gè)6個(gè)字節(jié)的ROWID ,并以此作為主鍵屋吨。

1.3.2 MyISAM存儲(chǔ)引擎

MyISAM存儲(chǔ)引擎不支持事務(wù)舱痘、表鎖設(shè)計(jì),支持全文索引离赫,主要面向一些OLAP數(shù)據(jù)庫(kù)應(yīng)用。

1.3.3 NDB 存儲(chǔ)引擎是一個(gè)集群存儲(chǔ)引擎塌碌,類(lèi)似于oracle的RAC集群渊胸,不過(guò)Oracle,Oracle RAC share everything 架構(gòu)不同是台妆,器結(jié)構(gòu)是share nothing的集群架構(gòu)翎猛,因此能夠提供更高的可用性胖翰。NDB的特點(diǎn)是數(shù)據(jù)全部放在內(nèi)存中,因此主鍵查詢(xún)(primary key lookups)的速度極快切厘,并且通過(guò)添加NDB數(shù)據(jù)存儲(chǔ)節(jié)點(diǎn)(data Node)可以線(xiàn)性地提高數(shù)據(jù)庫(kù)性能萨咳,是高可用、高性能的集群系統(tǒng)疫稿。

關(guān)于NDB存儲(chǔ)引擎有一個(gè)問(wèn)題值得注意培他,那就是NDB存儲(chǔ)引擎的鏈接操作JOIN時(shí)在MySQL數(shù)據(jù)庫(kù)層完成的,而不是在存儲(chǔ)引擎層完成的遗座,這意味著復(fù)雜的鏈接操作需要巨大的網(wǎng)絡(luò)開(kāi)銷(xiāo)舀凛,因此查詢(xún)速度很慢,如果解決了這個(gè)問(wèn)題途蒋,NDB存儲(chǔ)引擎的市場(chǎng)應(yīng)該是非常大的猛遍。

1.3.4 Memory存儲(chǔ)引擎

Memory存儲(chǔ)引擎(之前稱(chēng)之為HEAP存儲(chǔ)引擎)將表中的數(shù)據(jù)存放在內(nèi)存中,如果數(shù)據(jù)庫(kù)重啟或者發(fā)生奔潰号坡,表中的數(shù)據(jù)將消失懊烤。它非常適合用于存儲(chǔ)臨時(shí)數(shù)據(jù)的臨時(shí)表,以及數(shù)據(jù)倉(cāng)庫(kù)中的維度表宽堆。Memory存儲(chǔ)引擎默認(rèn)使用hash索引腌紧,而不是我們熟悉的B+樹(shù)索引。

Memory存儲(chǔ)引擎速度快日麸,但只支持表鎖寄啼,并發(fā)性能較差,并且不支持TEXT和BLOB列類(lèi)型代箭,最重要的是墩划,村粗變長(zhǎng)字段varchar時(shí)是按照定常字段方式進(jìn)行的,因此會(huì)浪費(fèi)內(nèi)存嗡综。

1.3.5 Archive 存儲(chǔ)引擎

Archve 存儲(chǔ)引擎只支持INSERT 和SELECT操作乙帮,從MySQL開(kāi)始支持索引。

1.3.6 Federated 存儲(chǔ)引擎

1.3.7 Maria 存儲(chǔ)引擎

Maria存儲(chǔ)引擎是新開(kāi)發(fā)的引擎极景,設(shè)計(jì)目標(biāo)主要是用來(lái)取代原有的MyISAM存儲(chǔ)殷勤察净,從而成為MySQL的默認(rèn)存儲(chǔ)引擎。Maria存儲(chǔ)引擎的開(kāi)發(fā)者是MySQL的創(chuàng)始人之一盼樟。Maria存儲(chǔ)引擎的特點(diǎn)是:支持緩存數(shù)據(jù)和索引文件氢卡,應(yīng)用了行鎖設(shè)計(jì),提供了MVCC功能晨缴,支持事務(wù)和非事務(wù)安全的選項(xiàng)译秦,以及更好的BLOB字符類(lèi)型的處理性能。

總結(jié): MySQL 的InnoDB 存儲(chǔ)引擎的效率在OLTP中效率更好,對(duì)于ETL MyISAM存儲(chǔ)引擎更具有優(yōu)勢(shì)筑悴。

當(dāng)數(shù)據(jù)量大于1000萬(wàn)時(shí)MySQL的性能會(huì)急劇下降嗎们拙?不!阁吝,MySQL是數(shù)據(jù)庫(kù)砚婆,不是文件,隨著數(shù)據(jù)行的增加突勇,性能當(dāng)然會(huì)有所下降装盯,但是這些下降不是線(xiàn)性的,如果用戶(hù)選擇了正確的存儲(chǔ)引擎与境,以及正確的配置验夯,再多的數(shù)據(jù)量MySQL也能承受。InnoDB上存儲(chǔ)超過(guò)1TB的數(shù)據(jù)摔刁,還有一些其他網(wǎng)站使用InnoDB存儲(chǔ)引擎挥转,處理插入/更新的操作平均800次/s

衡量標(biāo)準(zhǔn):

存儲(chǔ)容量的限制、事務(wù)的支持共屈、鎖的粒度绑谣、MVCC支持、支持的索引拗引、備份和復(fù)制等

各大存儲(chǔ)引擎

第2章 InnoDB存儲(chǔ)引擎

InnoDB是事務(wù)安全的MySQL存儲(chǔ)引擎借宵,設(shè)計(jì)上采用了類(lèi)似于Oracle數(shù)據(jù)庫(kù)的架構(gòu)。通常來(lái)說(shuō)矾削,InnoDB存儲(chǔ)引擎是OLTP應(yīng)用中核心代表的首選存儲(chǔ)引擎壤玫。同時(shí),也正式因?yàn)镮nnoDB的存在哼凯,才使得MySQL數(shù)據(jù)庫(kù)變得有魅力欲间。

2.1 InnoDB存儲(chǔ)引擎概述

最早由Innobase Oy公司開(kāi)發(fā),其特點(diǎn)行鎖設(shè)計(jì)断部、支持MVCC猎贴、支持外鍵、提供一致性非鎖定讀蝴光,同時(shí)被設(shè)計(jì)用來(lái)最有效地利用以及內(nèi)存和CPU她渴。

2.3 InnoDB體系架構(gòu)

Inno存儲(chǔ)引擎有多快內(nèi)存塊,可以認(rèn)為這些內(nèi)存組成了一個(gè)大的內(nèi)存池蔑祟,負(fù)責(zé)如下工作:

1趁耗、維護(hù)所有進(jìn)程/線(xiàn)程需要訪(fǎng)問(wèn)的多個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu)

2、緩存磁盤(pán)上的數(shù)據(jù)疆虚,方便快速地讀取苛败,同時(shí)在對(duì)磁盤(pán)文件的數(shù)據(jù)修改之前在這里緩存

3右冻、重做日志redo緩沖





后臺(tái)線(xiàn)程的主要負(fù)責(zé)刷新內(nèi)存池中的數(shù)據(jù),保證緩沖池的內(nèi)存緩存的是最近的數(shù)據(jù)著拭,此外將已經(jīng)修改的數(shù)據(jù)文件刷新到磁盤(pán)文件,同時(shí)保證在數(shù)據(jù)庫(kù)發(fā)生的異常情況下牍帚,Inno能恢復(fù)到正常的運(yùn)行狀態(tài)儡遮。

2.3.1 后臺(tái)線(xiàn)程

InnoDB存儲(chǔ)引擎是多線(xiàn)程的模型,因此其后臺(tái)有多個(gè)不同的后臺(tái)線(xiàn)程暗赶,負(fù)責(zé)處理不同的任務(wù)鄙币。

1、Master Thread

Master Thread 是一個(gè)非常核心的后臺(tái)線(xiàn)程蹂随,主要負(fù)責(zé)將緩沖池中的數(shù)據(jù)異步刷新到磁盤(pán)十嘿,保證數(shù)據(jù)的一致性,包括臟頁(yè)的刷新岳锁、合并插入緩沖(INSERT BUFFER)绩衷、UNDO頁(yè)的回收等。

2激率、IO Thread

在InnoDB存儲(chǔ)引擎中大量使用了AIO(Async IO)來(lái)處理寫(xiě)IO請(qǐng)求咳燕,這樣可以極大提高數(shù)據(jù)庫(kù)的性能。而IO Thread 的工作主要負(fù)責(zé)這些IO請(qǐng)求的回調(diào)(call back)處理乒躺。

3招盲、Purge(凈化) Thread

事務(wù)被提交后,其所使用的undolog可能不在需要嘉冒,因此需要PurgeThread來(lái)回收并分配的undo頁(yè)面曹货。Purge操作可以獨(dú)立到單獨(dú)的線(xiàn)程中锰霜,以此來(lái)減輕Master Thread的工作模软,從而提高CPU的使用率以及提升存儲(chǔ)引擎的性能。用戶(hù)可以再M(fèi)ySQL 數(shù)據(jù)庫(kù)的配置文件中添加如下命令來(lái)啟動(dòng)獨(dú)立的Purge ?Thread

innodb_Purge_threads=1

2.3.2內(nèi)存

1罪治、緩沖池

InnoDB 存儲(chǔ)引擎是基于磁盤(pán)存儲(chǔ)的娜遵,并將其中的記錄按照頁(yè)的方式進(jìn)行管理蜕衡。因此可將視為基于磁盤(pán)的數(shù)據(jù)庫(kù)系統(tǒng)。

緩沖池簡(jiǎn)單說(shuō)就是一塊內(nèi)存區(qū)域设拟,通過(guò)內(nèi)存的速度來(lái)彌補(bǔ)磁盤(pán)速度較慢對(duì)數(shù)據(jù)庫(kù)性能的影響慨仿,首先將從磁盤(pán)讀到的頁(yè)存放在緩沖池中,這個(gè)過(guò)程稱(chēng)為將頁(yè)“FIX”在緩沖池中纳胧。下一次在讀相同的也頁(yè)時(shí)镰吆,首先判斷該頁(yè)是否在緩沖池中,若在緩沖池中跑慕,稱(chēng)該頁(yè)在緩沖池中被命中万皿,直接讀取該頁(yè)摧找。否則讀取磁盤(pán)上的頁(yè)。

對(duì)于數(shù)據(jù)庫(kù)中也的修改操作牢硅,則首先修改緩沖池中的頁(yè)蹬耘,然后再以一定的頻率刷新到磁盤(pán)上。這里需要注意的是减余,頁(yè)從緩沖池刷新回磁盤(pán)的操作斌不是每次頁(yè)發(fā)生更新時(shí)觸發(fā)综苔,而是通過(guò)一種稱(chēng)為CheckPoint的機(jī)制刷新回磁盤(pán)。同樣這也是為了提高數(shù)據(jù)庫(kù)的整體性能位岔。

具體來(lái)看如筛,緩沖池中緩存的數(shù)據(jù)頁(yè)類(lèi)型有:索引頁(yè),數(shù)據(jù)頁(yè)抒抬、undo頁(yè)杨刨、插入緩沖(insert buffer)、自適應(yīng)哈希索引(adaptive hash index)擦剑、InnoDB存儲(chǔ)的鎖信息(lock info)妖胀、數(shù)據(jù)字典信息(data dictionary)等,InnoDB存儲(chǔ)引擎中內(nèi)存的結(jié)構(gòu)情況抓于。





允許多個(gè)緩沖池實(shí)例做粤,每個(gè)頁(yè)根據(jù)哈希值平均分配到不同的緩沖池實(shí)例中,這種做的好處是減少數(shù)據(jù)庫(kù)內(nèi)部的資源競(jìng)爭(zhēng)捉撮,增加數(shù)據(jù)庫(kù)的并發(fā)處理能力怕品。可以通過(guò)參加innodb_buffer_pool_instances來(lái)進(jìn)行配置巾遭,該值默認(rèn)為1

2肉康、LRU List、Free List和Flush List

通常來(lái)說(shuō)灼舍,數(shù)據(jù)庫(kù)中的緩沖池是通過(guò)LRU (Latest Recent Used)吼和,最近最少使用算法來(lái)進(jìn)行管理的。即最頻繁使用的頁(yè)在LRU列表的前端骑素,而最少使用的頁(yè)在LRU列表的尾端炫乓。當(dāng)緩沖池不能存放新讀取到頁(yè)時(shí),將首先釋放LRU列表中的尾端的頁(yè)献丑。

InnoDB存儲(chǔ)引擎中末捣,緩沖池中頁(yè)的大小默認(rèn)為16KB,同樣使用LRU算法對(duì)緩沖池進(jìn)行管理创橄,稍有不同的是InnoDB存儲(chǔ)引擎對(duì)傳統(tǒng)的LRU算法做了一些優(yōu)化箩做。在InnoDB的存儲(chǔ)引擎中,LRU列表中還加入了midpoint位置妥畏。新讀取到的頁(yè)邦邦,雖然是最新訪(fǎng)問(wèn)的頁(yè)面安吁,但并不是直接放入到LRU列表的首部,而是放入到LRU列表的midpoint位置燃辖。這個(gè)算法在InnoDB存儲(chǔ)引擎下稱(chēng)為midpoint insertion strategy鬼店,在默認(rèn)配置下,該文職在LRU列表長(zhǎng)度得5/8處黔龟。midpoin位置可由參數(shù)innodb_old_blocks_pct控制薪韩,在InnoDB存儲(chǔ)引擎中,把midpoint之后的列表稱(chēng)為old列表捌锭,之前的列表稱(chēng)為new列表÷奚樱可以簡(jiǎn)單的理解為new列表中的頁(yè)都是最為活躍的熱點(diǎn)數(shù)據(jù)观谦。

為什么不直接采用樸素的LRU算法,直接將讀取的頁(yè)放入到LRU列表的首部桨菜?這是因?yàn)槿糁苯訉⒆x取到的頁(yè)放入到LRU的首部豁状,那么某些SQL操作可能會(huì)使緩沖池中的頁(yè)被刷新出,從而影響緩沖池的效率倒得。常見(jiàn)的這類(lèi)操作為索引或數(shù)據(jù)的掃描操作泻红。這類(lèi)操作需要訪(fǎng)問(wèn)列表中的許多頁(yè),設(shè)置是全部的頁(yè)霞掺,而這些頁(yè)面通常來(lái)說(shuō)又僅在這次查詢(xún)操作中需要谊路,并不是活躍的熱點(diǎn)數(shù)據(jù)。如果頁(yè)被放入LRU列表的首部菩彬,那么非巢埃可能將所需要的熱點(diǎn)數(shù)據(jù)從LRU列表中移除,而在下一次需要讀取該頁(yè)時(shí)骗灶,InnoDB存儲(chǔ)引擎需要再次訪(fǎng)問(wèn)磁盤(pán)惨恭。

為了解決這個(gè)問(wèn)題,InnoDB存儲(chǔ)引擎引入了另一個(gè)參數(shù)來(lái)進(jìn)一步管理LRU列表耙旦,這個(gè)參數(shù)是innodb_old_blocks_time脱羡,用于表示頁(yè)讀取到mid位置后需要等待多久才會(huì)被加入到LRU列表的熱端。因此當(dāng)需要執(zhí)行上述所說(shuō)的SQL操作時(shí)免都,可以通過(guò)下面的方法盡可能使LRU列表中熱點(diǎn)數(shù)據(jù)不被刷出锉罐。

LRU列表用來(lái)管理已經(jīng)讀取的頁(yè),但當(dāng)數(shù)據(jù)庫(kù)剛啟動(dòng)時(shí)琴昆,LRU列表是空的氓鄙,即沒(méi)有任何頁(yè),這是頁(yè)都存放在free 列表中业舍,當(dāng)需要從緩沖池中分頁(yè)時(shí)抖拦,首先從Free列表中查找是否有可用的空閑頁(yè)面升酣,若有則將該頁(yè)從free列表中刪除,放入到LRU列表中态罪,否則根據(jù)LRU算法噩茄,淘汰LRU列表末尾的頁(yè)面,將該內(nèi)部空間分配給新的頁(yè)面复颈。當(dāng)頁(yè)從LRU列表的old部分加入到new部分時(shí)候绩聘,稱(chēng)此時(shí)操作為page made young,而因?yàn)閕nno_old_blocks_time的設(shè)置導(dǎo)致頁(yè)從old部分移動(dòng)new部分操作稱(chēng)為page not made young耗啦≡淦校可用通過(guò)命令SHOW ENGINE INNODB STATUS來(lái)觀(guān)察LRU列表及Free列表的使用情況和運(yùn)行狀態(tài)。

在LRU列表中的頁(yè)被修改后帜讲,稱(chēng)該頁(yè)為臟頁(yè)(dirty page)衅谷,即緩沖池中的頁(yè)和磁盤(pán)上的頁(yè)數(shù)據(jù)產(chǎn)生的不一致。這時(shí)數(shù)據(jù)庫(kù)會(huì)通過(guò)CHECKPOINT機(jī)制將臟頁(yè)刷新回磁盤(pán)似将,而Flush列表中获黔,LRU列表用來(lái)管理緩沖池中的頁(yè)的可用性,F(xiàn)luash列表用來(lái)管理將頁(yè)刷新回磁盤(pán)在验,二者互補(bǔ)影響玷氏。

3、重做日志緩沖

InnoDB存儲(chǔ)引擎的內(nèi)存區(qū)域除了有緩沖池外腋舌,還有重做日志緩沖(redo log buffer)盏触。InnoDB存儲(chǔ)引擎首先將重做日志信息放入到這個(gè)緩沖區(qū),然后按一定的頻率將其刷新到重做日志文件块饺。重做日志緩沖一般不需要社會(huì)得很大耻陕,因?yàn)橐话闱闆r下每秒鐘會(huì)將重做日志緩沖刷新到新的日志文件,因此用戶(hù)只需要保證每秒產(chǎn)生的事務(wù)在這個(gè)緩沖大小之內(nèi)即可刨沦,該值可由配置參數(shù)innodb_log_buffer_size控制诗宣,默認(rèn)為8MB




在通常情況下,8MB的重做日志緩沖池足以滿(mǎn)足絕大部分的應(yīng)用想诅,因?yàn)橹刈鋈罩驹谙盗腥N情況下會(huì)將重做日志緩沖中的內(nèi)容刷新到外掛磁盤(pán)的重做日志文件中召庞。

1、Master Thread每一秒將重做日志緩沖刷新到重做日志文件来破;

2篮灼、每個(gè)事務(wù)提交時(shí)會(huì)將重做日志緩沖刷新到重做日志文件;

3徘禁、當(dāng)重做日志緩沖池剩余空間小于1/2诅诱,重做日志日志緩沖刷新到重做日志文件。

4送朱、額外的內(nèi)存池

在InnoDB存儲(chǔ)引擎中娘荡,對(duì)內(nèi)存的管理是通過(guò)一種稱(chēng)為內(nèi)存堆(heap)的方式進(jìn)行的干旁。在對(duì)一些數(shù)據(jù)結(jié)構(gòu)本身的內(nèi)存進(jìn)行分配時(shí),需要從額外的內(nèi)存池中進(jìn)行申請(qǐng)炮沐,當(dāng)該區(qū)域的內(nèi)存不夠時(shí)争群,會(huì)從緩沖池中進(jìn)行分配,

2.4 checkpoint技術(shù)

緩沖池的設(shè)計(jì)目的為了協(xié)調(diào)CPU速度和磁盤(pán)速度的鴻溝大年。因此頁(yè)的操作首先都是在緩沖池中完成换薄。如果一條DML語(yǔ)句,如果update或者Delete改變了頁(yè)中國(guó)的記錄翔试,那么此時(shí)頁(yè)是臟的轻要,即緩沖池中的頁(yè)的版本要比磁盤(pán)的新。數(shù)據(jù)庫(kù)需要將新版本的頁(yè)從緩沖池刷新到磁盤(pán)垦缅。

倘若每次一個(gè)頁(yè)發(fā)生變化伦腐,就將新頁(yè)面的版本刷新到磁盤(pán),那么這個(gè)開(kāi)銷(xiāo)是非常大的失都。若熱點(diǎn)數(shù)據(jù)中在某幾個(gè)頁(yè)中,那么數(shù)據(jù)庫(kù)的性能將變得非常差幸冻。同時(shí)如果在從緩沖池將頁(yè)的新版本刷新到磁盤(pán)時(shí)發(fā)生了宕機(jī)粹庞,那么數(shù)據(jù)就不能恢復(fù)了。為了避免發(fā)生數(shù)據(jù)丟失的問(wèn)題洽损,當(dāng)前事務(wù)數(shù)據(jù)庫(kù)系統(tǒng)普遍都采用了Write Ahead Log策略庞溜,即當(dāng)事務(wù)提交時(shí),先重做日志碑定,再修改頁(yè)面流码。當(dāng)由于發(fā)生宕機(jī)導(dǎo)致數(shù)據(jù)丟失時(shí),通過(guò)重做日志來(lái)完成數(shù)據(jù)的恢復(fù)延刘,這也是事務(wù)ACID中D(Durability持久性)的要求漫试。

思考下面的場(chǎng)景,如果重做日志可以無(wú)限地增大碘赖,同時(shí)緩沖池也足夠大驾荣,能夠緩沖所有數(shù)據(jù)庫(kù)的數(shù)據(jù),那么是不需要將緩沖池中的頁(yè)的新版本刷新回磁盤(pán)普泡。因?yàn)楫?dāng)發(fā)生宕機(jī)的時(shí)候播掷,完全可以通過(guò)重寫(xiě)日志來(lái)恢復(fù)整個(gè)數(shù)據(jù)庫(kù)中的數(shù)據(jù)到宕機(jī)發(fā)生的時(shí)刻。但是這需要兩個(gè)前提條件:

1撼班、緩沖池可以緩存數(shù)據(jù)庫(kù)中所有的數(shù)據(jù)歧匈;

2、重做日志可以無(wú)限大

對(duì)于第一個(gè)前提條件砰嘁,有經(jīng)驗(yàn)的用戶(hù)都知道件炉,當(dāng)數(shù)據(jù)庫(kù)開(kāi)始創(chuàng)建時(shí)勘究,表中沒(méi)有任何數(shù)據(jù)。緩沖池的確可以緩存所有的數(shù)據(jù)庫(kù)文件

妻率。乱顾。。宫静。走净。

Checkpoint 技術(shù)的目的是解決一下幾個(gè)問(wèn)題:

1、縮短數(shù)據(jù)庫(kù)恢復(fù)的時(shí)間

2孤里、緩沖池不夠用伏伯,將臟頁(yè)刷新到磁盤(pán)

3、重做日志不可用時(shí)捌袜,刷新臟頁(yè)面说搅;

當(dāng)數(shù)據(jù)庫(kù)發(fā)生宕機(jī)時(shí),數(shù)據(jù)庫(kù)不需要重做所有的日志虏等,因?yàn)镃heckPoint之前的頁(yè)都已經(jīng)刷新回磁盤(pán)弄唧。故數(shù)據(jù)庫(kù)值需要對(duì)Checkpoint后的重做日志進(jìn)行恢復(fù),這樣就大大縮短了恢復(fù)時(shí)間霍衫。

此外候引,當(dāng)緩沖池不夠用時(shí),根據(jù)LRU算法會(huì)溢出最近最少使用的頁(yè)敦跌,若此頁(yè)面為臟頁(yè)澄干,那么需要強(qiáng)制執(zhí)行Checkpoint,將臟頁(yè)也就是也的新版本刷回磁盤(pán)柠傍。

重做日志出現(xiàn)不可用的情況是因?yàn)楫?dāng)前事務(wù)數(shù)據(jù)庫(kù)系統(tǒng)對(duì)重做日志的設(shè)計(jì)都是循環(huán)使用的麸俘,并不是讓其無(wú)限增大,這從成成本及管理上都是比較困難的惧笛,重做日志可以被重用的部分是指這些重做日志已經(jīng)不再需要从媚,即當(dāng)數(shù)據(jù)庫(kù)發(fā)生宕機(jī)時(shí),數(shù)據(jù)庫(kù)恢復(fù)操作不需要這部分的操作日志患整,因此這部分就可以被覆蓋重用静檬。若此時(shí)重做日志還需要使用,那么必須強(qiáng)制產(chǎn)生checkpoint并级,將緩沖池中的頁(yè)至少刷新到當(dāng)前重做日志的位置拂檩。

對(duì)于InnoDB存儲(chǔ)引擎而言言,其是通過(guò)LSN(log Sequence Number)來(lái)標(biāo)記版本的嘲碧。而LSN是8字節(jié)的數(shù)字稻励,其單位是字節(jié)。每個(gè)頁(yè)有LSN,重做日志中也有LSN望抽,checkpoint也有LSN加矛,

在InnoDB存儲(chǔ)引擎中,Checkpoint發(fā)生的時(shí)間煤篙,條件以臟頁(yè)的選擇都非常復(fù)雜斟览。而Checkpoint所做的事情無(wú)法外乎是將緩沖池中的昂頁(yè)刷回到磁盤(pán)。不同之處在于每次刷新多少頁(yè)到磁盤(pán)辑奈,每次從哪里取臟頁(yè)苛茂,以及什么時(shí)間觸發(fā)Checkpoint,在InnoDB存儲(chǔ)引擎內(nèi)部鸠窗,有兩種checkpoint妓羊,分別為:

1、Sharp Checkpoint

2稍计、Fuzzy Checkpoint

Sharp Checkpoint發(fā)生在數(shù)據(jù)庫(kù)關(guān)閉時(shí)將所有臟頁(yè)都刷新回磁盤(pán)躁绸,這是默認(rèn)的工作方式

參數(shù) innodb_fast_shutdown=1

但是若數(shù)據(jù)庫(kù)在運(yùn)行時(shí)也使用Sharp Checkpoint,那么數(shù)據(jù)庫(kù)的可用性就會(huì)受到很大的影響臣嚣,所以在InnoDB存儲(chǔ)引擎內(nèi)部使用Fuzzy CheckPoint進(jìn)行頁(yè)面刷新净刮,即只刷新一部分臟頁(yè),而不是刷新所有臟頁(yè)回磁盤(pán)硅则。

下面幾種情況的Fuzzy CheckPoint

1淹父、Master Thread Checkpoint

2、FLUSH_LRU_LIST_CheckPoint

3抢埋、Async/Sync Flush Checkpoint

4、Dirty page too much Checkpoint

Master Thread CheckPoint 以每秒或每十秒的速度從緩沖池的臟頁(yè)列表中刷新一定比例的頁(yè)回磁盤(pán)督暂。這個(gè)過(guò)程是異步的揪垄,即此時(shí)Inno搜索引擎開(kāi)源進(jìn)行其他的操作,用戶(hù)查詢(xún)線(xiàn)程不會(huì)阻塞逻翁。

FLUSH_LRU_LIST CheckPoint是因?yàn)镮nnoDB存儲(chǔ)引擎需要保證LRU列表中需要有差不多100多個(gè)空閑頁(yè)可供使用饥努。需要檢查L(zhǎng)RU列表中是都有足夠的可用的空間操作發(fā)生在用戶(hù)查詢(xún)線(xiàn)程中,顯然會(huì)阻塞用戶(hù)的查詢(xún)操作八回。倘若沒(méi)有100個(gè)可用空閑頁(yè)面酷愧,那么InnoDB存儲(chǔ)引擎會(huì)將LRU列表尾端的頁(yè)移除。如果這些有臟頁(yè)缠诅,那么需要進(jìn)行checkpoint溶浴,而這些頁(yè)是來(lái)自L(fǎng)RU列表的因此成為FLUSH_LRU_LIST checkpoint。

在mysql 5.6 也就是InnoDB1.2.x版本開(kāi)始管引,這個(gè)檢查被一個(gè)單獨(dú)的Page Cleanner線(xiàn)程進(jìn)行士败,并且用戶(hù)可以通過(guò)innodb_lru_scan_depth控制LRU列表中可用頁(yè)面的數(shù)量,該值默認(rèn)為1024

Async/Sync flush checkpoint 指的是重做日志文件不可用的情況,這是需要強(qiáng)制將一些頁(yè)刷新回磁盤(pán)谅将,而此時(shí)臟頁(yè)是從臟頁(yè)列表中選取的漾狼。若將已經(jīng)寫(xiě)入重做日志的LSN標(biāo)記為redo_lsn,將已經(jīng)刷新回磁盤(pán)最新也的LSN記為checkpoint_lsn

checkpoint_age = radio_lsn - checkpoint_lsn

再定義以下的變量:

async_water_mark = 75% * total_redo_log_file_size

sync_what_mark = 90% * total_log_file_size

2.5 Master Thread 工作方式

InnoDB存儲(chǔ)引擎的主要工作都是在一個(gè)獨(dú)立的后臺(tái)線(xiàn)程Master Thread中完成饥臂,

2.5.1 InnoDB 1.0.x版本之前的Master Thread

Master Thread 具有最高的線(xiàn)程的優(yōu)先級(jí)別逊躁。其內(nèi)部由多個(gè)循環(huán)loop組成:主循環(huán)loop、后臺(tái)循環(huán)backgroup loop隅熙、刷新循環(huán)flush loop稽煤、暫停循環(huán)suspend ?loop。Master Thread 會(huì)根據(jù)數(shù)據(jù)庫(kù)運(yùn)行的狀態(tài)在loop猛们,backgroud loop 念脯、flush loop 和suspend loop中進(jìn)行切換。

可以看到弯淘,loop循環(huán)通過(guò)thread sleep來(lái)實(shí)現(xiàn)绿店,這意味著所謂的每秒一次或者10秒一次的操作時(shí)不精確的,在負(fù)載很大的情況下可能會(huì)有延遲(delay)庐橙,只能說(shuō)大概在這個(gè)頻率下假勿。當(dāng)然InnoDB源代碼中還通過(guò)了其他方法來(lái)盡量保證這個(gè)頻率。

每秒一次的操作包括:

1态鳖、日志緩沖刷新到磁盤(pán)转培,即使這個(gè)事務(wù)還沒(méi)有提交(總是)

2、合并插入緩沖(可能)

3浆竭、至多刷新100個(gè)InnoDB的緩沖池中的臟頁(yè)到磁盤(pán)(可能)

4浸须、如果當(dāng)前沒(méi)有用戶(hù)活動(dòng),則切換到background loop(可能)

即使某個(gè)事務(wù)還沒(méi)有提交邦泄,InnoDB存儲(chǔ)引擎任然每秒會(huì)將重做日志緩沖中的內(nèi)容刷新到重做日志文件删窒。這一點(diǎn)是必須要知道的,因?yàn)檫@可以很好地解釋為什么再大的事務(wù)提交commit的時(shí)間也是很短的顺囊。

合并插入緩沖(Insert Buffer)并不是每秒都會(huì)發(fā)生的肌索。InnoDB存儲(chǔ)引擎會(huì)判斷當(dāng)前一秒內(nèi)發(fā)生的IO次數(shù)是否小于5,如果小于5次特碳,InnoDB認(rèn)為當(dāng)前的IO壓力很小诚亚,可以執(zhí)行合并插入緩沖的操作。

同樣午乓,刷新100個(gè)臟頁(yè)也不是每秒會(huì)發(fā)生的站宗,InnoDB存儲(chǔ)引擎通過(guò)判斷當(dāng)前緩沖池中臟頁(yè)的比例(buf_get_modified_ratio_pct)是否超過(guò)了配置文件中innodb_max_dirty_pages_pct 這個(gè)參數(shù)(默認(rèn)為90%),如果超過(guò)了這個(gè)閾值益愈,InnoDB存儲(chǔ)引擎認(rèn)為需要做磁盤(pán)同步的操作份乒,將100臟頁(yè)寫(xiě)入磁盤(pán)中。

10秒的操作

1、刷新100個(gè)臟頁(yè)到磁盤(pán)(可能的情況下)

2或辖、合并至多5個(gè)插入緩沖(總是)

3瘾英、將日志緩沖刷新到磁盤(pán)(總是)

4、刪除無(wú)用的undo頁(yè)(總是)

5颂暇、刷新100個(gè)或者10個(gè)臟頁(yè)到磁盤(pán)(總是)缺谴。

在以上的過(guò)程中,InnoDB存儲(chǔ)引擎會(huì)先判斷過(guò)去10秒內(nèi)磁盤(pán)的IO操作是否是小于200次耳鸯,湿蛔,如果是,InnoDB存儲(chǔ)引擎認(rèn)為目前有足夠的磁盤(pán)IO操作能力县爬,因此將100個(gè)臟頁(yè)刷新到磁盤(pán)阳啥。接著,InnoDB存儲(chǔ)引擎會(huì)合并插入緩沖财喳。不同于每秒一次操作時(shí)可能發(fā)生的合并插入緩沖的操作察迟,這次的合并插入緩沖操作總會(huì)在這個(gè)階段進(jìn)行。之后耳高,InnoDB存儲(chǔ)引擎會(huì)進(jìn)行一次將日志緩沖刷新到磁盤(pán)的操作扎瓶。這和每秒一次時(shí)發(fā)生的操作是一樣的。

接著InnoDB存儲(chǔ)引擎會(huì)執(zhí)行full purge操作泌枪,即刪除無(wú)用的Undo頁(yè)面概荷。對(duì)表進(jìn)行update、delete這類(lèi)操作碌燕,原先的行被標(biāo)記為刪除误证,但是因?yàn)橐恢滦宰x(consistance read)的關(guān)系,需要保留這些行版本的信息修壕。但是在full purge的過(guò)程中愈捅,InnoDB存儲(chǔ)引擎會(huì)判斷當(dāng)前事務(wù)系統(tǒng)中已被刪除的行是都可以刪除,比如有時(shí)候可能還有查詢(xún)操作需要讀取之前的版本undo的信息叠殷,如果可以刪除改鲫,InnoDB會(huì)立即將其刪除诈皿。從源代碼中可以發(fā)現(xiàn)林束,InnoDB存儲(chǔ)引擎在執(zhí)行full purge操作時(shí),每次最多嘗試回收20個(gè)undo頁(yè)稽亏。

然后InnoDB存儲(chǔ)引擎會(huì)判斷緩沖池頁(yè)面的比例buf_get_modified_ratio_pct壶冒,如果有超過(guò)50%的臟頁(yè)面,則刷新100個(gè)臟頁(yè)到磁盤(pán)截歉,如果臟頁(yè)的比例小于70%胖腾,則只需要刷新10%的臟頁(yè)面到磁盤(pán)。

若當(dāng)前沒(méi)有用戶(hù)活動(dòng)(數(shù)據(jù)庫(kù)空閑)或者數(shù)據(jù)庫(kù)關(guān)閉(shutdown),就會(huì)切換到這個(gè)循環(huán)咸作。background loop會(huì)執(zhí)行以下操作:

1锨阿、刪除無(wú)用的undo頁(yè)(總是)

2、合并20個(gè)插入緩存(總是)

3记罚、跳回到主循環(huán)(總是)

4墅诡、不斷刷新100個(gè)頁(yè)面知道服務(wù)條件(可能,跳轉(zhuǎn)到flush loop中完成)桐智。

若flush loop中也什么事情可以做末早,InnoDB存儲(chǔ)引擎會(huì)切換到suspend_loop,將Master Thread掛起说庭,等待事情的發(fā)生然磷。若用戶(hù)啟用enable了InnoDB存儲(chǔ)引擎,卻沒(méi)有使用任何InnoDB存儲(chǔ)引擎的表刊驴,那么Master Thread 總是處于掛起的狀態(tài)姿搜。

2.5.2 InnoDB1.2.x版本之前的Master Thread

InnoDB存儲(chǔ)引擎對(duì)于IO其實(shí)是有限制的,在緩沖池想磁盤(pán)刷新時(shí)缺脉,其實(shí)都做了一定的硬編碼(hard coding)痪欲。在磁盤(pán)技術(shù)飛速發(fā)展的今天,當(dāng)固態(tài)硬盤(pán)SSD出現(xiàn)時(shí)攻礼,這種規(guī)定在很大程度上限制了InnoDB存儲(chǔ)引擎對(duì)磁盤(pán)IO的性能业踢,尤其是寫(xiě)入性能。

InnoDB存儲(chǔ)引擎最大只會(huì)刷新100個(gè)臟頁(yè)到磁盤(pán)礁扮,合并20個(gè)插入緩沖知举。如果再寫(xiě)入密集的應(yīng)用程序中,每秒可能產(chǎn)生大于100個(gè)臟頁(yè)面太伊,如果是產(chǎn)生了大于20個(gè)插入緩沖的情況雇锡,Master Thread 似乎會(huì)“忙不過(guò)來(lái)”,或者說(shuō)它總是做的很慢僚焦。即使磁盤(pán)能在1秒內(nèi)處理多于100個(gè)臟頁(yè)的寫(xiě)入和20個(gè)插入緩存的合并锰提,但是由于hard coding。Master Thread 也只會(huì)選擇刷新100個(gè)臟頁(yè)和并20個(gè)插入緩沖芳悲。同時(shí)立肘,當(dāng)發(fā)生宕機(jī)需要恢復(fù)時(shí),由于很多數(shù)據(jù)還沒(méi)有刷新回磁盤(pán)名扛,會(huì)導(dǎo)致恢復(fù)的時(shí)間可能需要很久谅年,尤其是對(duì)于insert buffer來(lái)說(shuō)。經(jīng)過(guò)谷歌團(tuán)隊(duì)的修正提供了innodb_io_capacity的百分比來(lái)進(jìn)行控制肮韧,規(guī)則如下:

1融蹂、在合并插入緩沖時(shí)旺订,合并插入緩沖的數(shù)量為innodb_io_capacity值的5%

2、在從緩沖區(qū)刷新臟頁(yè)時(shí)超燃,刷新臟頁(yè)的數(shù)量為Innodb_io_capacity

如果用戶(hù)使用了SSD類(lèi)的磁盤(pán)区拳,或者將盡快磁盤(pán)做了RAID,當(dāng)存儲(chǔ)設(shè)備擁有更高的IO速度時(shí)意乓,玩可以將innodb_io_capacity的值調(diào)得再高點(diǎn)劳闹,知道符合磁盤(pán)IO的吞吐量為止。

另一個(gè)問(wèn)題是洽瞬,參數(shù)innodb_max_dirty_pages_pct默認(rèn)值的問(wèn)題本涕,在InnoDB 1.0.x版本之前,該值的默認(rèn)為90伙窃,意味著臟頁(yè)占緩沖池的90%菩颖,但是該值“太大”了,因?yàn)镮nnoDB存儲(chǔ)引擎在每秒刷新緩沖池和flush loop時(shí)會(huì)判斷這個(gè)值为障,如果該值大于innodb_max_dirty_pages_pct晦闰,才刷新100個(gè)臟頁(yè),如果有很大的內(nèi)存鳍怨,或者數(shù)據(jù)庫(kù)服務(wù)器的壓力很大呻右,這時(shí)刷新臟頁(yè)的速度反而會(huì)降低。同樣在數(shù)據(jù)庫(kù)的恢復(fù)階段可能需要更多的時(shí)間鞋喇。

在很多論壇上都有對(duì)這個(gè)問(wèn)題的討論声滥,有人甚至將這個(gè)值調(diào)到 20或10,然后測(cè)試發(fā)現(xiàn)性能所有提高侦香,但是將Innodb_max-dirty_pages_pct調(diào)到20或10會(huì)增加磁盤(pán)的壓力落塑,系統(tǒng)的負(fù)擔(dān)還是會(huì)有所增加的。google在這個(gè)問(wèn)題上進(jìn)行了測(cè)試罐韩,證明20并不是一個(gè)最優(yōu)值憾赁。從1.0.x版本開(kāi)始,inno_max_dity_pages_pct默認(rèn)值變?yōu)?5和google測(cè)試的80%比較接近散吵,這樣既可以加快刷新臟頁(yè)頻率龙考,又能保證磁盤(pán)IO的負(fù)載。

InnoDB 1.0.x版本帶來(lái)的另一個(gè)參數(shù)是innodb_adaptive_flushing(自適應(yīng)地刷新)

該值影響每秒刷新臟頁(yè)的數(shù)量矾睦,不刷新臟頁(yè)晦款;大于innodb_max_dirty_pages_pct時(shí),刷新100個(gè)臟頁(yè)顷锰。隨著inno_adaptive_flushing參數(shù)的引入柬赐,InnoDB存儲(chǔ)引擎會(huì)通過(guò)一個(gè)名為buf_flush_get_desired_flush_rate的函數(shù)來(lái)判斷需要刷新臟頁(yè)最合適的數(shù)量亡问。粗略地翻閱源代碼后發(fā)現(xiàn)buf_flush_get_desired_flush_rate通過(guò)判斷產(chǎn)生重做日志undo log的速度來(lái)決定適合的刷新臟頁(yè)的數(shù)量官紫。因此當(dāng)臟頁(yè)的比例小于innodb_max_dirty_pages_pct時(shí)肛宋,也會(huì)刷新一定量的臟頁(yè)。

還有一個(gè)改變:之前每次進(jìn)行full purge操作時(shí)束世,最多回收20個(gè)undo頁(yè)面酝陈,從InnoDB 1.0.x版本開(kāi)始引入?yún)?shù)innodb_purge_batch_size這個(gè)參數(shù)可以控制每次full purge回收的undo頁(yè)的數(shù)量。該參數(shù)的默認(rèn)值為20毁涉,并可以動(dòng)態(tài)地對(duì)其進(jìn)行修改沉帮。

2.5.3 InnoDB 1.2.x版本的Master Thread

srv_master_do_idle_tasks() 之前版本中每10秒的操作

srv_master_do_active_tasks()之前版本每秒的操作

從Master Thread線(xiàn)程分離到一個(gè)單獨(dú)的Page Cleaner Thread,從而減輕了Master Thread的工作贫堰,同時(shí)進(jìn)一步挺高了行的并發(fā)性穆壕。

2.6 InnoDB關(guān)鍵特性

1、插入緩沖 (Insert buffer)

2其屏、兩次寫(xiě)(double write)

3喇勋、自適應(yīng)哈希索引(Adaptive Hash Index)

4、異步IO(Async IO)

5偎行、刷新鄰接頁(yè)(Flush Neighbor Page)

一般情況下按照主鍵有序插入川背,如自增長(zhǎng),這樣的插入方式速度快蛤袒,

如遇到UUID或者輔助索引熄云,secondary index 并非有序,需要離散地訪(fǎng)問(wèn)非聚集索引頁(yè)妙真,由于隨機(jī)讀寫(xiě)的存在而導(dǎo)致插入操作性能下降缴允,而B(niǎo)+樹(shù)的特性決定了非聚集索引插入的離散性。

插入緩沖(insert buffer)

InnoDB存儲(chǔ)引擎開(kāi)創(chuàng)性地設(shè)計(jì)了Insert Buffer珍德,對(duì)于非聚集索引的插入或更新操作癌椿,不是每一次直接插入到索引頁(yè)中,而是先判斷插入的非聚集的引頁(yè)是都在緩沖池中菱阵,若在踢俄,則直接插入,若不在晴及,則先放入到一個(gè)Insert Buffer對(duì)象中都办。然后再以一定的頻率和情況進(jìn)行Insert buffer和輔助索引頁(yè)子節(jié)點(diǎn)的merge(合并)操作,這是通常能將多個(gè)插入合并到同一個(gè)操作中(因?yàn)樵谝粋€(gè)索引頁(yè)面中)虑稼,這就大大提高了非聚集索引插入的性能琳钉。

insert buffer 的使用需要滿(mǎn)足以下兩個(gè)條件:

1、索引是輔助索引(secondary index)

2蛛倦、索引不是唯一索引(unique)的

3歌懒、insert buffer的內(nèi)部實(shí)現(xiàn)

以前版本每個(gè)表都有一顆Insert buffer B+樹(shù)

現(xiàn)在的版本內(nèi)部只要一個(gè)B+樹(shù),負(fù)責(zé)對(duì)所有的表的輔助索引進(jìn)行Insert buffer溯壶。而這棵B+樹(shù)存放在共享表的空間中及皂,默認(rèn)也是在ibdata1甫男。因此試圖通過(guò)獨(dú)立表空間ibd文件恢復(fù)表中的數(shù)據(jù)時(shí),往往會(huì)導(dǎo)致CHECK TABLE失敗验烧。這是因?yàn)楸淼妮o助索引中的數(shù)據(jù)可能換在Insert Buffer中板驳,也是共享空間中,所以通過(guò)ibd文件進(jìn)行回復(fù)后碍拆,還需要進(jìn)行REPAIR TABLE操作來(lái)重建表上的所有輔助索引若治。

Insert Buffer 是一個(gè)B+樹(shù),因此由也是節(jié)點(diǎn)和非葉子節(jié)點(diǎn)組成感混。非葉子節(jié)點(diǎn)存放的是查詢(xún)的search key(鍵值)構(gòu)造如下



search key一共占用9個(gè)字節(jié)端幼,其中space表示帶插入記錄所在的表的表空間id,space占用4個(gè)字節(jié)弧满。marker占用1個(gè)字節(jié)静暂,它是用來(lái)兼容老版本的insert buffer,offset表示頁(yè)所在的偏移量谱秽,占4個(gè)字節(jié)

當(dāng)一個(gè)輔助索引要插入到頁(yè)(space洽蛀,offset)時(shí),如果這個(gè)頁(yè)不在緩沖池中疟赊,那么InnoDB存儲(chǔ)引擎首先根據(jù)上述規(guī)則茍澤一個(gè)search key郊供,接下來(lái)查詢(xún)insert buffer 這課B+樹(shù),然后再將這條記錄插入到Insert Buffer B+樹(shù)的葉子節(jié)點(diǎn)中

2.6.2兩次寫(xiě) doublewrite




2.6.3 自適應(yīng)哈希索引

哈希(hash)是一種非辰矗快的查找方式驮审,在一般的情況下這種查找的時(shí)間復(fù)雜度為O(1),即一般僅需要一次查找就能定位的數(shù)據(jù)吉执。而B(niǎo)+樹(shù)的查找次數(shù)疯淫,取決于B+樹(shù)的高度,在生產(chǎn)環(huán)境中戳玫,B+樹(shù)的高度一般為3-4層熙掺,古只需要3-4查詢(xún)。

InnoDB存儲(chǔ)引擎會(huì)監(jiān)控對(duì)表上各索引頁(yè)的查詢(xún)咕宿。如果觀(guān)察到建立哈希索引可以帶來(lái)速度提升币绩,則建立哈希索引,稱(chēng)之為自適應(yīng)哈希索引(Adaptive Hash Index府阀,AHI)缆镣。AHI是通過(guò)緩沖池的B+樹(shù)頁(yè)構(gòu)造而來(lái),因此建立的速度很快试浙,而且不需要對(duì)整張表構(gòu)建哈希索引董瞻。InnoDB存儲(chǔ)引擎會(huì)自動(dòng)根據(jù)訪(fǎng)問(wèn)的頻率和模式來(lái)自動(dòng)地為某些熱點(diǎn)建立哈希索引。

2.6.4異步IO

2.6.5刷新鄰接頁(yè)

Flush Neighbor Page(刷新緊鄰頁(yè))的特性田巴,其工作原理為:當(dāng)刷新一個(gè)臟頁(yè)時(shí)钠糊,Inno存儲(chǔ)引擎會(huì)檢測(cè)該頁(yè)所在區(qū)(extent)的所有頁(yè)挟秤,如果是臟頁(yè),那么一起進(jìn)行刷新眠蚂。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市斗躏,隨后出現(xiàn)的幾起案子逝慧,更是在濱河造成了極大的恐慌,老刑警劉巖啄糙,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笛臣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡隧饼,警方通過(guò)查閱死者的電腦和手機(jī)沈堡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)燕雁,“玉大人诞丽,你說(shuō)我怎么就攤上這事」崭瘢” “怎么了僧免?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)捏浊。 經(jīng)常有香客問(wèn)我懂衩,道長(zhǎng),這世上最難降的妖魔是什么金踪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任浊洞,我火速辦了婚禮,結(jié)果婚禮上胡岔,老公的妹妹穿的比我還像新娘法希。我一直安慰自己,他們只是感情好靶瘸,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布铁材。 她就那樣靜靜地躺著,像睡著了一般奕锌。 火紅的嫁衣襯著肌膚如雪著觉。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 48,970評(píng)論 1 284
  • 那天惊暴,我揣著相機(jī)與錄音饼丘,去河邊找鬼。 笑死辽话,一個(gè)胖子當(dāng)著我的面吹牛肄鸽,可吹牛的內(nèi)容都是我干的卫病。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼典徘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蟀苛!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起逮诲,我...
    開(kāi)封第一講書(shū)人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤帜平,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后梅鹦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體裆甩,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年齐唆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嗤栓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡箍邮,死狀恐怖茉帅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锭弊,我是刑警寧澤担敌,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站廷蓉,受9級(jí)特大地震影響全封,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜桃犬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一刹悴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧攒暇,春花似錦土匀、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至田度,卻和暖如春妒御,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背镇饺。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工乎莉, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓惋啃,卻偏偏與公主長(zhǎng)得像哼鬓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子边灭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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