2.1 InnoDB 概述
2.2 InnoDB 版本
2.3 InnoDB 體系架構
后臺線程的主要作用是負責刷新內存池中的數據, 保證緩沖池中的內存緩存的是最近的數據。 此外將已修改的數據文件刷新到磁盤文件, 同時保證在數據庫發生異常的情況下 InnoDB 能恢復到正常運行的狀態。
2.3.1 后臺線程
1 Master Thread
主線程主要負責將緩沖池中的數據異步刷新到磁盤, 保證數據的一致性, 包括臟頁的刷新、合并插入緩沖(Insert Buffer), Undo 頁的回收等。
2 IO Thread
IO 線程主要負責 AIO(async IO)請求的回調(call back)處理。 從 InnoDB 1.0.x 開始, read thread 和 write thread 分別增到到了 4 個, 用 innodb_read_io_threads 和 innodb_write_io_threads 參數進行設置。
上圖可以看到 IO Thread 0 為 insert buffer thread。 IO Thread 1 為 log thread 。 之后就是 innodb_read_io_threads 及 innodb_write_io_threads 來設置的讀寫線程, 且 讀線程的 ID 總是 小于寫線程。?
3 Purge Thread
事務被提交后, 其所使用的 undo log 可能不再需要, 因此需要 purge thread 來回收已經使用并分配的 undo 頁。 從 Innodb 1.2 版本開始, Innodb 支持多個 purge thread , 這樣做的目的是為了進一步加快 undo 頁的回收。 同時由于 purge thread 需要離散地讀取 undo 頁, 這樣也能更進一步利用磁盤的隨機讀取性能。
4 Page Cleaner Thread
作用是將之前版本中臟頁的刷新操作都放入到單獨的線程中來完成。 目的是為了減輕原 master thread 的工作及對于用戶查詢線程的阻塞, 進一步提高 Innodb 引擎的性能。
2.3.2 內存
1 緩沖池
Innodb 引擎是基于磁盤存儲的, 并將其中記錄按照頁的方式進行管理。 因此可將其視為基于磁盤的數據庫系統。
需要注意, 頁從緩沖池刷新回磁盤的操作并不是在每次頁發生更新時觸發, 而是通過一種稱為 checkpoint 的機制刷新回磁盤。 同樣是為了提高數據庫的整體性能。
緩沖池的配置通過參數 innodb_buffer_pool_size 來設置。
緩沖池中緩沖的數據頁類型有: 索引頁, 數據頁, undo 頁, 插入緩沖(insert buffer),自適應哈希索引(adaptive hash index), innodb 存儲的鎖信息(lock info), 數據字典信息(data dictionary)等.
參數 innodb_buffer_pool_instances 來配置允許有多少個緩沖池實例。
從 mysql 5.6 開始, 通過 information_schema 下的 innodb_buffer_pool_stats 來觀察緩沖狀態。
2 LRU List, Free List 和 Flush List
通常來說, 數據庫中的緩沖池是通過 LRU (Latest Recent Used)算法來管理的。
在 innodb 存儲引擎中, 緩沖池頁的大小默認為 16KB , 同樣用 LRU 算法對緩洪池進行管理。
midpoint insertion strategy: ?新讀取到的頁, 雖然是最新訪問的頁, 但并不是直接放入到 LRU 列表的首部, 而是放入到 LRU 列表的 midpoint 位置。 默認配置下, 該位置在 LRU 列表長度的 5 / 8 出。 midpoint 位置可由參數 innodb_old_blocks_pct 控制。 innodb_old_blocks_pct 默認值為 37 , 表示新讀取的頁插入到 LRU 列表尾端的 37% 位置(差不多 3 / 8 處)。 在 Innodb 中, 把 midpoint 之后的列表稱為 old 列表, 之前的列表 稱為 new 列表。 可以簡單理解為 new 列表的頁都是最為活躍的熱點數據。?
參數 innodb_old_blocks_time : 用于表示頁讀取到 mid 位置后需要等待多久才會被加入到 LRU 列表的熱端。
database pages 表示 LRU 列表中頁的數量。
pages made young 顯示了 LRU 列表中頁移動到前端的次數, 若服務器運行階段沒有改變 innodb_old_blocks_time 的值, 則 not young 為 0
modified db pages 顯示了臟頁的數量。
可通過表 innodb_buffer_page_lru 觀察每個 LRU 列表中每個頁的具體信息。
在 LRU 列表中頁被修改后, 該頁為臟頁(dirty page), 即緩沖池中的頁和磁盤上的頁的數據不一致, 這時數據庫會通過 checkpoint 機制將臟頁刷新回磁盤, 而 flush 列表中的頁即為臟頁列表。 需要注意, 臟頁既存在與 LRU 列表中, 也存在于 Flush 列表中。 LRU 列表用來管理緩沖池中頁的可用性, Flush 列表用來管理將頁刷新回磁盤。
3 重做日志緩沖
重做日志緩沖一般不需要設置得很大, 因為一般情況下每一秒會將重做日志緩沖刷新到日志文件, 因此用戶只需要保證每秒產生的事務量在扎個緩沖大小之內即可。 該值可由 innodb_log_buffer_size 控制, 默認 8MB。
重做日志在下列三種情況下會將重做日志緩沖中的內容刷新到外部磁盤的重做日志文件中:
1 master thread 每一秒將重做日志緩沖刷新到重做日志文件;
2 每個事務提交時會將重做日志緩沖刷新到重做日志文件;
3 當重做日志緩沖池剩余空間小于 1 / 2 時, 重做日志換成刷新到重做日志文件。
4 額外的內存池
2.4 CheckPoint 技術
倘若每次一個頁發生變化, 就將新頁的版本刷新到磁盤, 這個開銷就非常大了, 當前事務數據庫系統普遍都采用了 Write Ahead Log 策略, 即當事務提交時, 先寫重做日志,再修改頁。
checkpoint (檢查點)技術的目的是解決一下幾個問題:
1 縮短數據庫的恢復時間;
2 緩沖池不夠用時, 將臟頁刷新到磁盤;
3 重做日志不可用是, 刷新臟頁。
對 Innodb 引擎而言, 其是通過 LSN(Log Sequence Number) 來標記版本的。
在 Innodb 引擎內, 有兩種 checkpoint , 分別為:
1 Sharp Checpoint?
2 Fuzzy Checkpoint
Sharp Checkpoint 發生在數據庫關閉時將所有的臟頁都刷新回磁盤, 這是默認工作方式。
Fuzzy Checkpoint 使用 Fuzzy Checkpoint 進行頁刷新, 即只刷新一部分臟頁, 而不是刷新所有的臟頁回磁盤。
innodb_lru_scan_depth 控制 LRU 列表中可用頁的數量, 默認為 1024.
2.5 Master Thread 工作方式
http://www.cnblogs.com/xuanzhi201111/p/4040681.html
主線程邏輯:
2.6 InnoDB 關鍵特性
2.6.1 插入緩沖 (Insert Buffer)
1 Insert Buffer
Insert Buffer 的使用需要同時滿足以下兩個條件:
1 索引是輔助索引(secondary index);
2 索引不是唯一的(unique)。
2 Change Buffer
參數 innodb_change_buffering, 用來開啟各種 buffer 的選項。 參數可選值: inserts, deletes, purges, changes, all, none.
從 Innodb 1.2.x 開始, 通過 innodb_change_buffer_max_size 來控制 change buffer 最大使用內存的數量。 默認值為 25 , 表示 最多使用 1 / 4 ?的緩沖池內存空間。需要注意, 該參數的最大有效值為 50.?
3 Insert Buffer 的內部實現
Insert Buffer 的數據結構是一顆 B+ 數, 在現在的版本中, 全局只有一棵 Insert Buffer ?B + 樹, 負責對所有表的輔助索引進行 Insert Buffer。 其 非葉子節點存放的是查詢的 search key (鍵值)
4 Merge Insert Buffer
Merge Insert Buffer 的操作可能發生在一下幾種情況下:
1 輔助索引頁被讀取到緩沖池時;
2 Insert Buffer Bitmap 頁追蹤到該輔助索引頁已無可用空間時;
3 Master Thread
2.6.2 兩次寫 (Double Write)
double write 由兩部分組成, 一部分是內存中的 double write buffer, 大小為 2MB; 另一部分是物理磁盤上共享表空間中連續的 128 個頁, 即 2 個區, 大小同樣是 2MB。
2.6.3 自適應哈希索引 (Adaptive Hash Index)
Innodb 存儲引擎會自動根據訪問的頻率和模式來自動地為某些熱點頁建立哈希索引。
訪問模式一樣指的是查詢的條件一樣, 若交替進行上述查詢, 那么 Innodb 引擎不會對該頁構造 AHI。
哈希索引 只能用來搜索等值的查詢, 如 select *from table where index_col='xxx'. 而對于其他查找類型, 如范圍查找, 是不能使用哈希索引的, 因此出現了 non-hash searches / s 的情況。 通過 hash searches:non-hash searches 可以大概了解使用哈希索引后的效率。?
2.6.4 異步 IO (Async IO)
2.6.5 刷新臨接頁 (Flush Neighbor Page)
參數 innodb_flush_neighbors, 用來控制該特性。 對于傳統機械硬盤建議啟用該特性, 對于固態硬盤有著超高 IOPS 性能的磁盤, 則建議將該參數設置為 0, 即關閉次特性。
2.7 啟動、關閉與恢復
參數 innodb_fast_shutdown 影響著表的存儲引擎 Innodb 的行為。 參數可取值為 0, 1, 2 , 默認為 1.
為 0 時, ?表示數據庫關閉時, innodb 需要完成 所有的 full purge 和 merge insert buffer, 并且將所欲的臟頁刷新回磁盤。 如果在進行 Innodb 升級時, 必須將這個參數調為 0, 然后再關閉數據庫。
為 1 時, ?默認值, 表示不需要完成 full purge 和 merge insert buffer 操作, 單是在緩沖池中的一些數據臟頁還是會刷新回磁盤。
為 2 時, 不完成 full purge 和 merge insert buffer 操作, 也不將緩沖池中的數據臟頁寫會磁盤, 而是將日志都寫入日志文件。這樣不會有任何事物丟失, 單下次 Mysql 啟動時, 會進行恢復操作。
需要注意的是, 在設置了參數 innodb_force_recovery 大于 0 后, 用戶可以對表進行 select , create 和 drop 操作, 但 Insert ,update 和delete 這類 DML 操作是不允許的。?