前言

InnoDB做為一款成熟的跨平臺(tái)數(shù)據(jù)庫(kù)引擎,其實(shí)現(xiàn)了一套高效易用的IO接口,包括同步異步IO,IO合并等。本文簡(jiǎn)單介紹一下其內(nèi)部實(shí)現(xiàn),主要的代碼集中在os0file.cc這個(gè)文件中。本文的分析默認(rèn)基于MySQL 5.6,CentOS 6,gcc 4.8,其他版本的信息會(huì)另行指出。

基礎(chǔ)知識(shí)

WAL技術(shù) : 日志先行技術(shù),基本所有的數(shù)據(jù)庫(kù),都使用了這個(gè)技術(shù)。簡(jiǎn)單的說(shuō),就是需要寫(xiě)數(shù)據(jù)塊的時(shí)候,數(shù)據(jù)庫(kù)前臺(tái)線程把對(duì)應(yīng)的日志先寫(xiě)(批量順序?qū)懀┑酱疟P(pán)上,然后就告訴客戶(hù)端操作成功,至于真正寫(xiě)數(shù)據(jù)塊的操作(離散隨機(jī)寫(xiě))則放到后臺(tái)IO線程中。使用了這個(gè)技術(shù),雖然多了一個(gè)磁盤(pán)寫(xiě)入操作,但是由于日志是批量順序?qū)?,效率很高,所以客?hù)端很快就能得到相應(yīng)。此外,如果在真正的數(shù)據(jù)塊落盤(pán)之前,數(shù)據(jù)庫(kù)奔潰,重啟時(shí)候,數(shù)據(jù)庫(kù)可以使用日志來(lái)做崩潰恢復(fù),不會(huì)導(dǎo)致數(shù)據(jù)丟失。
數(shù)據(jù)預(yù)讀 : 與數(shù)據(jù)塊A“相鄰”的數(shù)據(jù)塊B和C在A被讀取的時(shí)候,B和C也會(huì)有很大的概率被讀取,所以可以在讀取B的時(shí)候,提前把他們讀到內(nèi)存中,這就是數(shù)據(jù)預(yù)讀技術(shù)。這里說(shuō)的相鄰有兩種含義,一種是物理上的相鄰,一種是邏輯上的相鄰。底層數(shù)據(jù)文件中相鄰,叫做物理上相鄰。如果數(shù)據(jù)文件中不相鄰,但是邏輯上相鄰(id=1的數(shù)據(jù)和id=2的數(shù)據(jù),邏輯上相鄰,但是物理上不一定相鄰,可能存在同一個(gè)文件中不同的位置),則叫邏輯相鄰。
文件打開(kāi)模式 : Open系統(tǒng)調(diào)用常見(jiàn)的模式主要三種:O_DIRECT,O_SYNC以及default模式。O_DIRECT模式表示后續(xù)對(duì)文件的操作不使用文件系統(tǒng)的緩存,用戶(hù)態(tài)直接操作設(shè)備文件,繞過(guò)了內(nèi)核的緩存和優(yōu)化,從另外一個(gè)角度來(lái)說(shuō),使用O_DIRECT模式進(jìn)行寫(xiě)文件,如果返回成功,數(shù)據(jù)就真的落盤(pán)了(不考慮磁盤(pán)自帶的緩存),使用O_DIRECT模式進(jìn)行讀文件,每次讀操作是真的從磁盤(pán)中讀取,不會(huì)從文件系統(tǒng)的緩存中讀取。O_SYNC表示使用操作系統(tǒng)緩存,對(duì)文件的讀寫(xiě)都經(jīng)過(guò)內(nèi)核,但是這個(gè)模式還保證每次寫(xiě)數(shù)據(jù)后,數(shù)據(jù)一定落盤(pán)。default模式與O_SYNC模式類(lèi)似,只是寫(xiě)數(shù)據(jù)后不保證數(shù)據(jù)一定落盤(pán),數(shù)據(jù)有可能還在文件系統(tǒng)中,當(dāng)主機(jī)宕機(jī),數(shù)據(jù)有可能丟失。
此外,寫(xiě)操作不僅需要修改或者增加的數(shù)據(jù)落盤(pán),而且還需要文件元信息落盤(pán),只有兩部分都落盤(pán)了,才能保證數(shù)據(jù)不丟。O_DIRECT模式不保證文件元信息落盤(pán)(但大部分文件系統(tǒng)都保證,Bug #45892),因此如果不做其他操作,用O_DIRECT寫(xiě)文件后,也存在丟失的風(fēng)險(xiǎn)。O_SYNC則保證數(shù)據(jù)和元信息都落盤(pán)。default模式兩種數(shù)據(jù)都不保證。
調(diào)用函數(shù)fsync后,能保證數(shù)據(jù)和日志都落盤(pán),因此使用O_DIRECT和default模式打開(kāi)的文件,寫(xiě)完數(shù)據(jù),需要調(diào)用fsync函數(shù)。
同步IO : 我們常用的read/write函數(shù)(Linux上)就是這類(lèi)IO,特點(diǎn)是,在函數(shù)執(zhí)行的時(shí)候,調(diào)用者會(huì)等待函數(shù)執(zhí)行完成,而且沒(méi)有消息通知機(jī)制,因?yàn)楹瘮?shù)返回了,就表示操作完成了,后續(xù)直接檢查返回值就可知道操作是否成功。這類(lèi)IO操作,編程比較簡(jiǎn)單,在同一個(gè)線程中就能完成所有操作,但是需要調(diào)用者等待,在數(shù)據(jù)庫(kù)系統(tǒng)中,比較適合急需某些數(shù)據(jù)的時(shí)候調(diào)用,例如WAL中日志必須在返回客戶(hù)端前落盤(pán),則進(jìn)行一次同步IO操作。
異步IO : 在數(shù)據(jù)庫(kù)中,后臺(tái)刷數(shù)據(jù)塊的IO線程,基本都使用了異步IO。數(shù)據(jù)庫(kù)前臺(tái)線程只需要把刷塊請(qǐng)求提交到異步IO的隊(duì)列中即可返回做其他事情,而后臺(tái)線程IO線程,則定期檢查這些提交的請(qǐng)求是否已經(jīng)完成,如果完成再做一些后續(xù)處理工作。同時(shí)異步IO由于常常是一批一批的請(qǐng)求提交,如果不同請(qǐng)求訪問(wèn)同一個(gè)文件且偏移量連續(xù),則可以合并成一個(gè)IO請(qǐng)求。例如,第一個(gè)請(qǐng)求讀取文件1,偏移量100開(kāi)始的200字節(jié)數(shù)據(jù),第二個(gè)請(qǐng)求讀取文件1,偏移量300開(kāi)始的100字節(jié)數(shù)據(jù),則這兩個(gè)請(qǐng)求可以合并為讀取文件1,偏移量100開(kāi)始的300字節(jié)數(shù)據(jù)。數(shù)據(jù)預(yù)讀中的邏輯預(yù)讀也常常使用異步IO技術(shù)。
目前Linux上的異步IO庫(kù),需要文件使用O_DIRECT模式打開(kāi),且數(shù)據(jù)塊存放的內(nèi)存地址、文件讀寫(xiě)的偏移量和讀寫(xiě)的數(shù)據(jù)量必須是文件系統(tǒng)邏輯塊大小的整數(shù)倍,文件系統(tǒng)邏輯塊大小可以使用類(lèi)似

延伸閱讀

學(xué)習(xí)是年輕人改變自己的最好方式-Java培訓(xùn),做最負(fù)責(zé)任的教育,學(xué)習(xí)改變命運(yùn),軟件學(xué)習(xí),再就業(yè),大學(xué)生如何就業(yè),幫大學(xué)生找到好工作,lphotoshop培訓(xùn),電腦培訓(xùn),電腦維修培訓(xùn),移動(dòng)軟件開(kāi)發(fā)培訓(xùn),網(wǎng)站設(shè)計(jì)培訓(xùn),網(wǎng)站建設(shè)培訓(xùn)學(xué)習(xí)是年輕人改變自己的最好方式