一、前言
MySQL 最早由瑞典 MySQL AB 公司開發,該公司由 Monty 在 1995 年創立;MySQL 這個名字來源於 Monty 的大女兒 My。它的成功不僅僅是因爲免費,還有它的可靠性,穩定性和一些其它閃亮的特性。而 MySQL 中最核心的組建就是存儲引擎,令人意外的是 Innodb 引擎的發展進程竟然比 MySQL 要早,甚至在時間上遠遠甩開了一些高級編程語言。
值得一提的是,MySQL 和 linux 兩大開發源碼的陣營都出自芬蘭人之手,按照採訪 Monty 時他的說法,芬蘭人的本性就是固執和討厭放棄,截止現在 Linus 在 Linux 方面堅持了 30 年,而 Monty 也堅持了 20 年,他們的這種專注和堅持是值得我們學習的。
理解 Innodb 的第一步就是要熟悉 show engine innodb shatus 中輸出結果的含義,今天我們一起來學習它。
二、環境及輸出
- 操作環境:MySQL 5.7.28
- 輸出結果:
show engine innodb status\G
- 上面就是輸出結果,主要包含一些 innodb 引擎中的一些狀態,共有 10 個部分
BACKGROUND THREAD
:後臺 Master 線程狀態SEMAPHORES
:等待線程的列表及事件計數器,評估當前負載情況LATEST DETECTED DEADLOCK
:最新的幾次死鎖信息數據(只有發送死鎖時顯示)latest foreign key error
:最近幾次外鍵錯誤信息(只有發生錯誤時顯示)TRANSACTIONS
:innodb 事務統計信息FILE I/O
:顯示的是I/O輔助線程的狀態及性能計數器的狀態INSERT BUFFER AND ADAPTIVE HASH INDEX
:insert buffer pool 和 AHI 狀態LOG
:innodb 事務日誌 Redo 的統計信息BUFFER POOL AND MEMORY
:innodb buffer pool 使用統計信息ROW OPERATIONS
:ROW 操作和其它統計信息
三、內容解析
show engine innodb status
顯示的不是當前實時
的狀態,而是過去某個時間範圍
的狀態,上圖爲輸出的時間信息表示:查詢信息爲過去的 21 秒內,每兩秒內平均值
介紹:Master 線程三種狀態
- Master 線程是 innodb 引擎中最
重要
的線程,主要負責異步刷新數據
維護數據一致性
處理,有三種
工作狀態,每次循環都會根據數據庫
狀態選擇
其中一種工作狀態。 Active
是 Master 線程判斷系統處於忙碌狀態
時選擇的工作模式,它的循環數量增加主要與數據變化有關,與查詢無關。Idle
是 Master 線程判斷系統處於空閒狀態
選擇的工作模式,Idle 與 Active 兩種工作模式做的事情幾乎都一樣,只不過執行時間間隔
不同。shutdown
是在關閉實例時纔會選擇的工作模式。
解析:輸出解析
- 上圖是一臺比較
空閒
的實例
運行的結果,可以看到srv_active
爲 567 而srv_idle
則爲 1756519 遠遠大於 active 循環次數,所以可以對比兩 active 和 idle 的值來判斷
系統的負載
情況。 - 相對的如果實例輸出的結果
srv_idle
遠遠大與active
則可以認爲系統處於忙碌狀態
。
- FILE I/O 主要是關於 innodb 中
IO Thread
線程的相關信息。 - IO Thread 線程分別爲:
Read thread
、Write thread
、Insert buffer thread
、Log thread
使用的是異步
I/O 模型,處理不同類型的 I/O 請求和回調。 - 可以通過上圖信息清晰看到 IO Thread 的信息,其中
read thread
和write thread
線程分別
有4
個,Log thread 和 insert buffer thread 線程分別各一個,其中 read 和 write 線程可以根據參數
來調整。
BUFFER POOL AND MEMORY
主要是關於 Innodb 的緩存池
管理相關數據
Total large memory allocated
:innodb 分配的總內存
(byte)Dictionary memory allocated
:innodb數據字典分配的內存數(byte)Buffer pool size
:緩衝池分配的頁數Free buffers
:緩衝池空閒頁數Database pages
:LRU 列表中分配的數據頁
(LRU 是 innodb 管理緩存
的算法)Old database pages
:LRU 在old sublist
部分頁的數量Modified db pages
:buffer pool 中的數據髒頁
Pending reads
:掛起讀的數量
LRU
算法介紹:數據庫緩存
技術中都會使用的算法
- 算法思想:LRU 的
本質
是讓數據頁
在緩存中長時間保留
,提高查詢訪問效率
,但是緩存是有限
的,LRU 的作用就是減少
重複數據頁加載頻率
。 - 算法解析:LRU 是 innodb 中的一種
定製化算法
,首先它會有一個列表
,叫LRU LIST
上面存放一些數據頁
,這個列表就是Database pages
上圖是 6885 個數據頁 大約 1MB innodb 在 LRU 列表中加入了參考點
,叫midpoint
當訪問到的數據頁不在緩衝區
會直接將磁盤中的數據頁調到緩衝區隊列;innodb 不是將數據頁直接插入到緩衝區隊列
的隊頭
,而是插入 LRU 列表的midpoint
位置。默認配置 midpoint 是在整個列表長度的5/8
處,和數學中的黃金分割 0.618 很接近,midpoint 是由innodb_old_blocks_pct
控制。LRU LIST
在 midpoint 之前的列表稱爲young sublist
或者sublist of new block
裏面的數據是熱數據,而LRU LIST
在midpoint
之後的列表稱爲old sublist
或者sublist of old block
。
- 算法過程:當
緩衝池
不能存放新讀取
到的頁時,將首先釋放 LRU 列表中尾端
的頁。當一些全表掃描如果進入sublist of new block
區域,整個 LRU 就會是性能瓶頸
,這種情況叫緩存污染
。爲了解決這種問題,innodb 加入了innodb_old_blocks_time
來表示數據頁讀取到 mid 位置後需要等待
多久纔會進入 LRU 列表的熱端
,默認爲1000 毫秒
,可以設置此參數保證熱點數據
不會被輕易刷出。
Innodb 引擎日誌
管理
- 上圖主要展示的是關於 innodb
日誌
相關,所以我們需要了解 innodb 引擎中日誌的作用,主要有兩種類型的日誌redo log
重做日誌和undo log
回滾日誌,分別存儲在 ib_logfile 和 ibdata 文件中。 - LSN 介紹:redo 日誌的作用是爲了維護事務的
持久性
和故障自動恢復
,都會基於 LSN 日誌序列號,LSN 是一個一直遞增的整型數字
(8 個字節),表示事務寫入到日誌的字節總量
,每個數據頁和重做日誌及checkpoint
都有 LSN。 checkpoint
:innodb 的刷盤
機制,可以將buffer poo
l 中的數據髒頁
刷寫到磁盤
。- redo 日誌工作機制:上面已經提過 redo 日誌主要維護事務的
持久化存儲
,我們現在認識LSN
和checkpoint
後仔細討論,當執行一條DML
語句時 innodb 會將硬盤中需要改動
的數據頁加載到 buffer pool正常邏輯
是在內存
中修改完成後再刷到磁盤
中,但是這樣有風險如果此時宕機
buffer pool 中沒有刷寫到到數據就會失效
,所以 innodb 會先將改動數據記錄加載到redo buffer pool
中然後再由它快速刷寫到redo 的物理存儲空間
中,此時如果宕機那麼原數據+改動數據記錄
就可以恢復
到宕機前的狀態
,這個恢復過程就是故障自動恢復
機制,MySQL 在啓動時會對比數據和 ib_logfile 中到 LSN 編號,如果不一樣則認爲數據不一致
,啓動自動故障恢復機制恢復數據後纔會啓動
成功。 - undo 日誌工作機制:undo 日誌主要
維護
的事務的原子性
,事務執行過程會將事務的反操作
記錄到 undo物理空間
中,默認在ibdata
共享文件中,但是 ibdata 太過龐大5.7 版本
後可以通過innodb_undo_tablespaces
指定需要匹配幾個 undo 文件。
LOG
數據解析:
Log sequence number
:LSN1 當前系統 LSN 最大值,新的事務日誌將在原日誌基礎上生成(LSN1 + 新日誌的大小)Log flushed up to
:LSN2 當前已經寫入日誌文件的 LSNPages flushed up to
:LSN3 當前最舊的數據髒頁對應的 LSN 執行 checkpoint 時可以直接將此 LSN 寫入到日誌文件。Last checkpoint at
:LSN4 當前已經被 checkpoint 寫入的 LSN
- 主要是
等待線程
的列表及事件計數器和一些鎖
的情況,可以評估系統的負載情況
。 - 目前這部分相對來說用的比較少,網絡上的資料比較模糊,詳細描述後補。
- 死鎖一般是
事務
相互等待
對方資源,最後形成環路
造成的。出現死鎖 MySQL 也會檢測到,然後通過回滾事務
解決。發生死鎖會增加系統負擔
,MySQL錯誤日誌
也會記錄死鎖問題,查詢到根源
然後解決和避免
死鎖問題。當然也可以通過上圖發現和結果最近的幾次死鎖問題。除了死鎖系統還有外鍵錯誤記錄。
三、總結
- 上面我們介紹 innodb
體系結構
中比較重要
的指標,從show engine innodb shatus
的結果就可以看出 innodb 引擎的一個大體結構,四個線程、buffer pool、redo 和 undo、鎖機制和相關特性,當然這只是冰山一角
,要想真正理解 innodb 還需要多花點時間
。