本篇文章是對Innodb存儲引擎的概念進行一個總體的歸納,innodb存儲引擎的概念是mysql數據庫中最關鍵的幾個概念之一,涉及的內容很是的廣;因爲我的的理解能力有限若是有不對的地方還見諒。前端
MySQL對應InnoDB版本mysql
MySQL 5.1》InnoDB 1.0.X算法
MySQL 5.5》InnoDB 1.1.Xsql
MySQL 5.6》InnoDB 1.2.X數據庫
後臺線程express
1.Master Thread緩存
負責將緩衝池中的數據異步刷新到磁盤,保證數據的一致性;包括刷新髒頁、合併插入緩衝、undo頁的回收。服務器
2.IO Thread併發
innodb存儲引擎中大量使用了AIO(Async IO)來處理寫IO請求來提升數據庫的併發性能,共有四類IO線程,分別是:insert buffer thread、log thread、read thread、write thread。其中read thread和write thread分別有四個線程,能夠經過innodb_read_io_threads和innodb_write_io_threads來配置。異步
SHOW VARIABLES LIKE 'innodb_%io_threads' 或者 SHOW ENGINE INNODB STATUS \G;
3.Purge Thread線程
purge Thread線程用來回收事務提交後其被分配的undo頁,默認是開啓的,能夠經過innodb_purge_threads=1配置多個Purge Thread線程。
show variables like 'innodb_purge_threads';
配置2個Purge thread,只能修改配置文件配置,不能在線修改
innodb_purge_threads=2
4.Page Cleaner Thread
用於多版本控制功能中回收delete和update操做產生的髒頁,用來執行將髒頁刷新到磁盤。
5.Binlog Dump線程
當配置了複製後,會在主服務器生成一個binlog Dump線程來讀取二進制修改記錄。
6.lock線程
用於鎖控制和死鎖檢測
內存
不要理解覺得內存中就只有innodb buffer,還包括重作日誌緩衝、額外的內存池(目前還不知道好比join buffer、order buffer、key buffer、table cache buffer等是在緩衝池內部仍是獨立於緩衝池在內存中)
1.緩存池
緩存的數據主要有數據頁、索引頁、重作日誌頁(undolog)、節點信息、系統數據、插入緩衝、自適應哈希索引、數據字典、鎖信息等
查看緩衝池的大小,單位字節,轉化爲MB須要/1024/1024 show variables like 'innodb_buffer_pool_size';
默認innodb有8個緩衝池,能夠經過配置innodb_buffer_pool_instances
查詢
show engine innodb status \G;
或者
SELECT * FROM information_schema.innodb_buffer_pool_status;
讀操做:
數據是以頁爲存儲單位,在緩衝池中緩存了不少數據頁,當第一次讀取時首先將頁從磁盤讀取到緩存池中,當下一次再去讀相同的數據頁時若是該也在緩存池中就直接從緩衝池中讀取而不須要再去磁盤讀,最理想的方式是將全部的磁盤數據都緩存到緩衝池中可是這得內存足夠大才行。
修改操做
innodb存儲引擎對數據的修改也是先修改緩衝池中的數據頁(若是存在),而後根據必定的頻率刷新到磁盤來修改數據文件,這涉及到checkpoint機制,
插入操做(insert buffer)
由於數據是按照彙集索引的順序排列的,全部針對彙集索引的插入通常會很是快,而非彙集索引的插入就不必定是順序的,這個時候須要離散的訪問非彙集索引頁,插入的性能每每會不好,有一種狀況可能例外就是非彙集索引的時間字段,而時間每每是順序的,這種狀況會比較快,針對非彙集索引的這種狀況就引入了插入緩衝。
innodb中引入了插入緩衝(insert buffer),insert buffer只針不惟一的非彙集索引,對於非彙集索引的插入和更新操做不是每次直接插入到索引文件中,而是先判斷插入的非彙集索引頁是否存在緩衝池中,若是存在則直接插入緩衝池的非彙集索引文件中,不然先放入到一個insert buffer對象當中,可是給人的感受它已經插入到了索引文件中,可是實際並無,而後再以必定的頻率插入到索引文件當中,在這個過程當中若是存在多個相同的索引頁的插入會合並插入,大大的提升了非彙集索引的插入性能,
由於每次插入是先插入到緩衝池當中不去查找索引頁來判斷記錄的惟一性,由於去作判斷須要去離散查找,因此插入緩衝不針對惟一性的非彙集索引。
在密集寫操做的狀況下,插入緩衝會佔用過多的緩衝池的內存,默認最大能夠佔到50%,源代碼中的IBUF_POOL_SIZE_PER_MAX_SIZE=2,若是將其修改成3,則最大隻能使用1/3的緩衝池的內存。
2.LRU List、Free List、Flush List
innodb緩衝池中的頁默認大小爲16KB,緩衝池經過LRU(Latest Recent Used 最新少使用)算法來進行管理,將最頻繁的使用的頁放在LRU列表的前端,而最近少使用的頁放在尾端,當緩存池中的空間不足的時會先刪除尾端的頁來釋放空間。LRU有一個midpoint位置,默認在LRU的37%的位置,左邊表示old列表,右邊表示new列表(熱點數據),新插入緩衝池中的頁先放在midpoint的位置,若是新插入的頁一來就移動到new列表的話可能會致使new列表中的某些活動也被移除到old列表中,好比表掃描操做一次性可能須要訪問不少的數據頁而這些數據頁可能之後不多被使用,新插入的頁什麼時候纔會被被放入new列表中呢,爲了解決這個問題innodb引入了innodb_old_blocks_time參數,該參數用來控制新插入的數據頁在mid位置多久後才被加入到new列表中。
查看midpoint的位置,若是以爲熱點數據空間須要更多能夠將該值設小 show variables like 'innodb_old_blocks_pct'
查詢innodb_old_blocks_time值,單位毫秒,默認是1000毫秒即1秒
show variables like 'innodb_old_blocks_time'
查看緩衝池中全部頁的信息,包括空閒頁,全部的數據頁*16KB其實也就是緩衝池的總大小. select * from information_schema.INNODB_BUFFER_PAGE; 查看LUR列表的信息,包括new list和old list可是不包括free list,表中的字段記錄了當前的數據頁的信息,包括緩衝池ID,頁的類型(數據頁、索引頁、undo log、other),表名,索引名,是不是old list的頁,是否屬於壓縮頁(能夠將本來16K的頁壓縮爲1K、2K、4K、8K),壓縮頁的大小,是否屬於髒頁。 select POOL_ID,LRU_POSITION,SPACE,PAGE_TYPE,FLUSH_TYPE,NEWEST_MODIFICATION,OLDEST_MODIFICATION,INDEX_NAME,DATA_SIZE,COMPRESSED_SIZE,COMPRESSED,IS_OLD from information_schema.INNODB_BUFFER_PAGE_LRU;
OLDEST_MODIFICATION>0表示髒頁的數量也就是(modified db pages)
IS_OLD='YES'表明OLD List頁
COMPRESSED<>0表明壓縮頁
flush list:值的就是LRU中的髒頁,flust list存在於New List中,即OLDEST_MODIFICATION>0(modified db pages)
3.日誌緩衝(log buffer):對應innodb日誌文件
查看重作日誌緩衝 show variables like 'innodb_log_buffer_size%';
InnoDB存儲引擎首先將重作日誌信息先放入到重作日誌緩衝中,而後按照必定的頻率將其刷新到重作日誌文件當中。默認緩衝大小是8M,8M基本能夠知足需求,不須要配置太大的重作日誌緩衝。
刷新機制:
1.Master Thread 每一秒將重作日誌緩衝刷新到重作日誌文件;
2.每一個事務提交時會將重作日誌緩衝刷新到重作日誌文件;
3.當重作日誌緩衝池剩餘空間小於1/2時
注意:innodb_log_buffer_size的大小應該要比最大的事務大小要打,不然事務還未提交innodb_log_buffer_size就已經寫滿就須要進行刷新操做,會形成一個事務須要屢次進行磁盤日誌刷新操做,致使效率低。
4.額外的內存
平時咱們的服務器MySQL進程所使用的內存會比配置的InnoDB緩衝池的內存要大,那是由於MySQL除了緩衝池中緩存的內存額外還須要一部份內存用來控制緩衝池內部的一些資源信息,好比LRU、鎖資源、等待等。
CheckPoint機制
爲了解決CPU和磁盤直接速度的問題採用了緩衝池,因此對數據的操做都是先在緩衝池中完成,緩衝池中的數據頁每每比磁盤上的數據頁要新,咱們將在緩衝池中已經修改可是還未應用到磁盤的數據頁叫「髒頁」,數據頁最終仍是須要更新到磁盤中,中間會涉及到CheckPoint機制。
同時爲了解決由於忽然服務器停機致使緩衝池中還將來得及刷新到磁盤的髒頁丟失的問題,加入了重作日誌文件(重作日誌文件默認是配置2個,默認名稱是ib_logfile開頭,重作日誌文件默認大小是48M,兩個重作日誌文件採起循環寫的方式),當事務提交時先寫重作日誌,當發生服務器停機後能夠經過重作日誌來完成恢復(服務器重啓以後本身默認會恢復),因此得保證重作日誌文件有剩餘空間,默認機制是當重作日誌文件空間達到75%-90%時就刷新一部分髒頁到磁盤同時清空對應的重作日誌空間。
每次刷新多少頁到磁盤:
Sharp Checkpoint:數據庫關閉時將全部髒頁都刷新回磁盤,默認方式,參數:innodb_fast_shutdown=1
Fuzzy Checkpoint:刷新部分髒頁,具體分爲如下四種狀況
1.Master Thread Checkpoint
Master Thread每隔幾秒鐘從緩衝池中將髒頁刷新回磁盤
2.FLUSH_LRU_LIST CheckPoint
在5.6版本以後須要保證LRU默認存在1024個可用頁,若是可用頁不足1024頁刷新部分髒頁回磁盤,經過參數「innodb_lru_scan_dapth」配置。
3.Async/Sync Flush Checkpoint
指的是由於重作日誌文件空間不足致使的同步或異步刷新髒頁回磁盤,當重作日誌空間已使用的空間達到75%-90%就觸發異步刷新,若是超過90%就觸發同步刷新,通常不會觸發同步刷新操做,除非重作日誌文件過小而且進行LOAD DATA的BULK INSERT操做。
4.Dirty Page too much
保證緩衝池中髒頁的比例,當緩衝池中的髒頁比例達到75%時就觸發刷新髒頁操做,經過參數「innodb_max_dirty_pages_pct」配置。
innodb存儲引擎的概念很是的多,隨便一個知識點都不止一篇文章能夠寫下,因此本篇只是會總體作一個描述後面會針對每個知識點進行更細的分析。
備註: 做者:pursuer.chen 博客:http://www.cnblogs.com/chenmh 本站點全部隨筆都是原創,歡迎你們轉載;但轉載時必須註明文章來源,且在文章開頭明顯處給明連接。 《歡迎交流討論》 |