innoDB的各個版本對比
innoDB的整體架構(gòu)
后臺線程
- master thread
1.賦值將緩沖池中的數(shù)據(jù)異步刷到磁盤墓懂,保證數(shù)據(jù)的一致性焰宣。
- 刷新臟頁,合并插入緩沖捕仔,UNDO頁的回收等
- IO tread
1.innodb采用AIO來處理寫IO匕积,而IO thread就是處理這些IO請求的回調(diào)
2.Io thread有:write盈罐,read,insert bufeer和log
3.可以通過innodb_read_io_threads和innodb_write_io_threads來設(shè)置read和write的線程數(shù)闪唆,insert bufeer和log固定為1個
- purge thread
1.undo log用于存放事務(wù)提交前原始的數(shù)據(jù)盅粪,如果事務(wù)已經(jīng)提交了,則undo可以通過purge thread回收
2.可以設(shè)置多個purge thread 回收undo 頁
- page cleaner thread
1.將臟頁的刷新操作都放入到page cleaner thread
內(nèi)存
- 緩沖池
1.innodb中的記錄按照頁的方式進行管理悄蕾。
2.將磁盤讀到的頁放在緩沖池票顾,這個過程稱為將頁FIX在緩沖區(qū)
3.對頁修改是先修改緩沖池的頁,然后再以一定的頻率刷新到磁盤上
4.頁從緩存池刷新會磁盤的操作并不是每次頁發(fā)生變更的時候帆调,而是通過checkpoint機制
5.通過innodb_buffer_pool_size來設(shè)置和這個緩沖池大小
6.內(nèi)存數(shù)據(jù)對象包含以下奠骄,其中緩沖池包含:數(shù)據(jù)頁,插入緩沖番刊,鎖信息含鳞,索引頁,自適應(yīng)哈希索引芹务,數(shù)據(jù)字典信息
7.可以有多個緩沖池實例民晒,每個頁根據(jù)hash值平均分配到不同的緩沖池實例,這樣就減少數(shù)據(jù)庫內(nèi)部資源競爭
8.innodb_buffer_pool_instances來設(shè)置多少個緩沖值實例锄禽。
- LRU List,Free List 和Flush List
1.LRU List,Free List 和Flush List這三個是用來管理緩沖池內(nèi)容的方式
2.LRU最近最少使用方式潜必,前端存放使用最頻繁,最少使用存放尾部沃但。最新讀到的頁面磁滚,將首先存放在尾部。(innodb做了優(yōu)化宵晚,把最新的頁存放在midpoint位置垂攘,默認是在LRU列表長度的5/8)
3.在innodb中把midpoint之后的稱為old,之前的稱為new淤刃。即new是最活躍的熱點數(shù)據(jù)
4.設(shè)置innodb_old_blocks_time晒他,來標識頁讀取到mid位置后需要等待多久才會被加入到LRU列表的熱端
5.數(shù)據(jù)庫剛啟動LRU是空的,頁都存放在Free列表中逸贾,我們獲取頁陨仅,優(yōu)先從free中獲取
- LRU列表淘汰的末尾頁,將該內(nèi)存空間分配給新的頁
7.當支持壓縮頁后铝侵,頁變?yōu)?1KB,2KB,4KB和8KB灼伤,對于非16KB的頁管理,通過unzip_LRU進行管理
8.我們正常得到的LRU頁包含unzip_LRU
9.unzip_LRU分配頁方法(比如想獲取4KB),首先檢查4KB的unzip_LRU列表是否有可用的空閑頁咪鲜,沒有的話檢查8KB的列表狐赡,如果有則將8KB分成2個4KB,放入到4KB列表疟丙,若還是得不到則從16KB申請一個頁颖侄,拆分成1個8KB的頁鸟雏,2個4KB的頁,分別存放對應(yīng)的unzip_LRU
10.在LRU列表中被修改的頁览祖,我們稱之為臟頁崔慧,通過checkPoint機制將臟頁刷新會磁盤,flush列表就是臟頁列表
11.臟頁即存在于LRU也存在Flush列表(因為還需要使用)
- redo log buffer
- innodb會將重做日志信息放入到這個緩沖區(qū)穴墅,然后以一定的頻率將其刷新到重做日志文件(redo log file)
2.通過設(shè)置innodb_log_buffer_size設(shè)置這個redo log buffer
3.以下三種情況會將redo log buffer刷新到redo log file:master thread每秒鐘會刷新惶室,當事務(wù)提交時候,當重做buffer剩余空間大小小于一半
- 額外的內(nèi)存池
checkpoint
- 1.為了避免在內(nèi)存中臟頁還未刷到磁盤玄货,系統(tǒng)宕機導(dǎo)致數(shù)據(jù)都是皇钞,采用了write ahead log
- 2.write ahead log:即事務(wù)提交的時候,先寫redo log file(即把redo log buffer 轉(zhuǎn)化為文件)
- 3.如果redo log file 太大了會導(dǎo)致松捉,數(shù)據(jù)庫啟動時候恢復(fù)需要很長時間夹界,且成本太高
- 4.checkPoint:縮短數(shù)據(jù)庫的恢復(fù)時間,緩沖池不夠用時候?qū)⑴K頁刷新到磁盤隘世,重做日志不可用的時候刷新臟頁可柿。
- 5.宕機之后,checkpont之前的頁都已經(jīng)刷新到磁盤丙者,只需要對checkpoint后的重做日志進行恢復(fù)复斥。
- 6.單緩沖池不夠用,LRU會溢出最近最少使用的頁溢出械媒,若是臟頁則會執(zhí)行checkpoint目锭,即將臟頁刷新到磁盤
- 7.因為對重做日志都是循環(huán)使用的,當我們重做日志快用滿了纷捞,這個時候如果還想使用重做日志痢虹,那么需要把內(nèi)存中國對應(yīng)的頁給刷到磁盤,才可以覆蓋那部分被刷到磁盤頁對應(yīng)的重做日志
- checkpoint的類型:sharpCheckPoint
主儡,F(xiàn)uzzy CheckPoint.
- 9.sharpCheckPoint:發(fā)生在數(shù)據(jù)庫關(guān)閉時候奖唯,將所有的臟頁刷新回磁盤,這是默認的工作方式糜值,通過參數(shù)innodb_fast_shutdown=1
- 10.Fuzzy CheckPoint.:master thread checkPoint丰捷,F(xiàn)LUSH_LRU_LIST checkPoint,Async/Sync flush check point,Dirty Page too much check point
- master thread checkPoint:每個一段時間刷新一定比例臀玄,是異步操作瓢阴。
- 12.FLUSH_LRU_LIST checkPoint:被移除LRU列表的臟頁會被回收.通過page cleaner thread 去操作
- 13.Async/Sync flush check point:只重做日志不可用畅蹂,這時候強制將一些頁刷新回到磁盤健无,放入到page cleaner thread 中操作
- Dirty Page too much check point:強制刷新一部分臟頁到磁盤
masterThread的工作方式
最初該線程內(nèi)部又多個loop組成,loop液斜,background loop累贤,flush loop叠穆,suspend loop
loop 分為 每秒操作和每十秒操作,
loop 每秒操作:日志緩沖刷新到磁盤臼膏,即時事務(wù)還沒提交(總是)硼被,合并插入緩沖(可能),至多刷新100個臟頁到磁盤(可能)渗磅,如果當前沒有事務(wù)提交嚷硫,則契合到backgroup loop
loop 每十秒操作:刷新100個臟頁(可能),合并至多5個插入緩沖(總是)始鱼,將日志緩沖刷新到磁盤(總是)仔掸,刪除無用的undo(總是),刷新100個或者10個臟頁到磁盤
background loop:數(shù)據(jù)庫空閑医清,或者關(guān)閉起暮,就會切換到這個循環(huán)。
background loop:刪除無用的undo(總是)会烙,合并20個插入緩沖(總是)负懦,調(diào)到主循環(huán)(總是),不斷刷新100個頁直到符合條件(可能柏腻,跳轉(zhuǎn)到flush loop中完成)
如果flsuh loop 沒有臟頁要刷新纸厉,則會切換到suspend_loop,將master thread 掛起
之后的改革就是 合并插入緩沖時候五嫂,合并插入緩沖的數(shù)量是 innodb_io_capacity的5%残腌,從緩沖區(qū)刷新臟頁的數(shù)量就是innodb_io_capacity
剔除了innodb_adaptive_flushing ,用來判斷每次刷新多少臟頁
把 刷新臟頁的操作轉(zhuǎn)移給page cleaner thread
innodb關(guān)鍵特性
- 插入緩沖:其是物理頁的一部分贫导,不是緩沖區(qū)的一個部分抛猫,對于插入或者更新的時候,先判斷對應(yīng)的非聚集索引頁是否在緩沖池孩灯,若是在直接插入闺金,不在的話則先放入到一個insert buffer中,然后在以一定的頻率和情況進行insert buffer和輔助索引的葉子結(jié)點的merge峰档。需要索引不是唯一且是輔助索引败匹。以后的change buffer 作用與insert buffer一樣只是還可以作用于delete等
我們每次刪除記錄都是現(xiàn)將記錄標識位已刪除,然后再真正刪除
兩次寫:如果數(shù)據(jù)寫到頁讥巡,寫了一半發(fā)生宕機掀亩,那么這個頁就是被損壞,如果通過redo log無法對其redo 因為redo log 是對頁進行物理操作欢顷,,寫入發(fā)生失效槽棍,我們先通過頁的副本替換頁,然后在進行重做。這就是double write
double write包含double write buffer 為2M炼七,還有磁盤上128個連續(xù)頁缆巧,大小同樣為2M。在對緩沖池的臟頁進行刷新時候豌拙,并不直接寫盤陕悬,而是先將臟頁數(shù)據(jù)復(fù)制到內(nèi)存中double write buffer ,然后double write 分為2次 1m的去寫按傅,直接同步到磁盤捉超。因為double write的頁是連續(xù)的所以開銷不大,然后我們在將double write buffer 寫入各個表空間
-
我們在恢復(fù)空間只需要將double write 頁中的數(shù)據(jù)直接復(fù)制到表空間文件唯绍,在應(yīng)用重做日志
redo 是物理和邏輯日志的結(jié)合狂秦,每次記錄哪個頁,發(fā)生了什么操作推捐,當我們頁被污染了裂问,這個時候再去寫,很有可能造成數(shù)據(jù)不一致牛柒。所以需要換一個新的頁
為啥redo 不需要 doubble write
這個博客記錄了 為啥我們同時需要double write和redo :https://www.cnblogs.com/geaozhang/p/7241744.html
自適應(yīng)哈希索引:innodb觀察到如果給表加上hash索引可以提高速度堪簿,即對熱點查詢建立自適應(yīng)hash,
異步io:read ahead和臟頁的刷新都是依靠AIO
刷新鄰接頁:刷新一個臟頁皮壁,發(fā)現(xiàn)這個頁所在去的所有頁椭更,如果是臟頁,那么久一起進行刷新蛾魄,這樣的好處是通過AIO將多個IO寫入合并為一個
對于不怎么臟的臟頁 也刷新了虑瀑,或者固態(tài)硬盤不需要。所以可以關(guān)閉