前言

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

基礎(chǔ)知識

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

延伸閱讀

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