1.錯誤日志 error log
- 錯誤日志 error.log :記錄了MySQL啟動、運行、關閉過程中出現的問題。
2.慢查詢日志
- 記錄超過閥值時間的所有SQL語句,默認10s,等於10s不記。
- 1.5.1記錄到slow_log表中。
- log_output參數可以指定慢查詢日志輸出格式,默認FILE , 可以設置成TABLE,這樣就可以查看表了。
3.查詢日志
- 記錄所有日志無論是否正確執行。
4.二進制日志 binary log
- 記錄關於事務的具體操作內容,就是對事務操作的描述,並未記錄數據,屬於邏輯日志。
- 記錄對MYSQL數據庫執行更改的所有操作,但是不包括 SELECT和SHOW,這類沒有進行更改的操作。
- 作用:恢復數據,復制數據,查看數據庫是否被攻擊, 主從復制。
5.重做日志redo log
- redo log 是是屬於InnoDB引擎的文件(InnoDB引擎還有表空間文件),其他日志文件是屬於MySQL的。
- 記錄每個頁的更改情況,為了壓縮日志只記錄了與原頁不同的數據(這里埋下了2次寫的隱患)屬於物理日志。
- 重做日志至少2個,記錄數據修改之后的值,無論事務是否提交都會記錄。
- 寫滿一個重做日志接着寫下一個,全寫滿之后再重寫寫第一個。
- 作用:當數據庫宕機之后可以使用重做日志來恢復到宕機之前時刻。
6.回滾日志undo log
- 主要用於記錄事務行為,屬於邏輯日志。
- 用於回滾事務。
7.InnoDB內存
- InnoDB引擎所有數據都被邏輯的放入一個空間中,稱為表空間,表空間有划分為一個個段,段又分為區,區有划分為頁,頁中存有一行行數據。
- InnoDB引擎存儲是基於磁盤的,數據以頁的形式管理,數據頁從磁盤讀到內存進行處理,之后寫回磁盤。
- 緩沖池就是為了解決CPU和磁盤之間的速度差異,如圖所示
- 管理緩沖池內存區域
-
- 為了管理緩沖池InnoDB引擎使用了3個列表進管理。
- Free List :數據庫剛啟動時內存中還沒有讀入任何頁,這時候這些內存就有Free List來管理,這些緩沖池中的頁也叫作 free buffer。
- LRU List : 管理已讀頁,從磁盤讀入數據后,會從Free List中判斷有沒有可用的free buffer,如果有寫入數據,此時該頁數據和磁盤數據一致,該頁也叫作 clean buffer ,這些與磁盤一致的頁交由LRU List管理 。
-
之所以叫LRU List 是因為他采用LRU 最近最少使用算法,把clean buffer 緩存頁管理起來,這樣一來熱點數據就在列表頭部,不熱點的頁就在列表尾部。
-
如果遇到Free List沒有能使用的 free buffer時,那么就把LRU List 末尾的數據釋放,變為free buffer 以供新的page讀入。之所以這樣是因為這些頁是不是熱點數據,對這些數據的修改寫入概率小,即使釋放之后讀取概率也不大,可以減少IO。
-
- Flush List : LRU List中的數據被修改,與磁盤不一致那么就叫做 dirty buffer 或者 臟頁(dirty page)。Flush List 就是來管理臟頁的,他和LRU List 管理方式一樣,采用LRU 算法進行管理,頻繁被修改的臟頁放在列表頭部,不頻繁修改的臟頁,一定時間刷入磁盤。
-
這三個列表結構是雙向鏈表,他們是邏輯上的,並不是物理上存在的。所以出現臟頁並不是從LRU List 復制到 Flush List,內存彌足珍貴。所以LRU 和 Flush List都有臟頁。
- LRU List 是用來管理可用緩存頁的可用性,而Flush 是將臟頁刷新到磁盤。
- InnoDB 對LRU算法進行了改進,讀入數據后並不是直接插入列表頭部,而是插入列表的5/8處的minpoit點,這樣做的好處就是如果讀入大量的頁但這些頁不是熱點數據,他們也不會把真正列表頭部的熱點數據刷新出去。並且設置了一個時間閥值,超過這個時間就把他加入鏈表熱點數據部分。
8.InnoDB內存刷新機制
- 關系型數據庫都講究 日志先行策略,就是一條DML語句進入數據庫之后都會先寫日志,再寫數據庫文件。
-
存儲引擎工作線程 Master Thread 開始工作
- Master Thread 一直處於線程有四個循環狀態中。
- 主循環: loop
- 后台循環:background loop
- 刷新循環:flush loop
- 暫停循環 :suspend loop
- 主循環 loop : 有2種操作 每1s 和 每10s操作
- 每1s:
- 重寫日志緩存刷新到重寫日志磁盤(總是)
- 合並插入緩存(可能)
- 最多刷新100個臟頁到磁盤(可能)
- 如果沒有用戶活動,則切換到后台循環(可能)
- 每10s:
- 合並最多5個插入緩沖。(總是)
- 將重寫日志刷新到磁盤(總是)
- 執行Full purge 操作 刪除無用的 undo 頁最多20個(總是)
- 刷新100或者10個臟頁到磁盤(總是)
- 每1s:
- Master Thread 一直處於線程有四個循環狀態中。
-
將UNDO信息寫入undo表空間的回滾段中;
-
修改緩存頁並將redo日志數據刷新到磁盤。
- 重寫日志刷新觸發有2個地方,一是主線循環每秒的刷新,而是 提交時的innodb_flush_log_at_trx_commit參數設置
- 參數設置為0,則提交時不用將重做日志寫入磁盤,而是等待主循環每秒刷新。
- 參數設置為1,則提交時同步寫入磁盤。默認為1
- 參數設置為2,則異步寫入磁盤。
-
寫二進制日志
-
Commit 完成
-
臟頁刷新到磁盤
- 2次寫
9.InnoDB 引擎特性
-
插入緩沖
- 插入緩沖是針對使用非聚集索引本身。
- 他使對普通索引上的DML操作從隨機IO變成了順序IO
- 要符合2個條件
- 索引是輔助索引
- 索引不是唯一索引。
-
- 對於聚集索引因為其葉子節點是連續的所以 並且葉子節點就是表數據,所以插入時可以順序查找插入,插入的再多IO次數也較少,而且數據插入和索引插入是一起的速度比較快。
- 而非聚集索引其葉子節點雖然是連續的,但是葉子節點不存數據只存數據指針,指向的數據在磁盤上並不一定是按順序的,不能順序插入。插入的多了IO次數也就多了。
- 如果是唯一索引,那就要檢查是不是唯一的這就增加了IO次數違背減少IO次數的初衷。
- 首先從磁盤查找要插入的索引頁(索引也是表數據以頁為單位存放),查到位置后不會執行插入操作(如果插入可能引起節點分裂,每次插入都會有隨機IO)而是在判斷索引頁是否在緩存中。
- 如果在緩存中則直接插入緩存中的索引頁,如果不在則 先放到一個 Change Buffer 中,在一定情況下再合並到葉子節點中。
- Change Buffer 也是一個B+樹結構,它的葉子節點有一定規則,記錄了磁盤中非聚集索引對應的葉子節點位置。
- 符合一定條件后會將Change Buffer中的葉子節點一次合並到磁盤非聚集索引的葉子節點上。這樣的合並只會引起一次節點分裂,減少了IO次數。
- 由於在Change Buffer中會對插入節點
-
兩次寫
-
- 插入緩沖帶來了性能上的提高,而兩次寫則保證了數據頁的安全性。
- 臟頁被寫入磁盤時有可能一個頁只寫了一部分數據后發生宕機,造成數據丟失,這種情況被稱為 部分寫失效。
- 發生部分寫失效,無法使用重做日志恢復數據,這是因為 重做日志並沒有記錄一個頁的全部數據,而只是記錄了頁的改變數據,比如 一個頁數據為 1111 1111 修改后為 1110 1111,重做日志只記錄 “偏移量4 修改為0”。
- 由於發生部分寫失效時 頁本身已經被損壞,所以即使重做日志也不知道是什么樣的數據 在 第四位改為0,所以重做日志無濟於事。
- 臟頁被寫入磁盤前先寫入一個doublewrite buffer

- doublewriter buffer 分2個每次1M寫入共享表空間,共享表是連續的所以這個開銷並不大。
- 之后再寫入磁盤。
-
自適應哈希索引
- InnoDB存儲引擎自動根據訪問頻率和模式來自動的為某些熱點數據建立哈希索引
- 訪問頻率不用多說,訪問模式就是 根據某一相同的條件 訪問,如:where name = "java" 訪問100次可能為naem = java 建立哈希索引,如果 where name = "java" 訪問50次where name = "java" and id = 2 訪問50 可能並不會為name = java 建立哈希索引。


