mysql innodb存儲引擎學習(1)

mysql & innodb存儲引擎

一、mysql體系結構
    mysql從體系上可以分爲三個層次,連接層、sql層、存儲引擎層。
1.1 連接層
    通過socket等方式接受客戶端的連接,數據I/O,線程處理,處理通信協議,密碼驗證等功能。
1.2 sql層
    包含權限判斷、查詢緩存、解析器、預處理、查詢優化器、緩存和執行計劃。在一條sql語句在服務端被反序列出來後都需要經過這樣鏈式的處理:對查詢語句進行解析、優化改寫最後生成執行計劃。最後通過調用存儲引擎的API接口訪問數據。
1.3 存儲引擎層
    mysql最核心的存儲引擎爲innodb。它支持事物、行鎖、mvcc多版本併發控制適用於OLTP業務系統。
    innodb由三個部分組成 1 內存結構 2 線程 3 磁盤文件
    磁盤文件保存了數據庫相關的所有數據,而線程負責對這些數據進行讀寫。內存結構保存了innodb運行需要的數據結構,緩存磁盤數據信息和提供日誌緩衝。
    
二、innodb體系架構
2.1 內存結構
    mysql內存的組成分爲SGA系統全局區域和PGA程序緩存區。主要看SGA:
    1. 緩衝池是一塊內存區域,通過內存的速度來彌補磁盤速度較慢對數據庫性能的影響。該區域主要用來緩存innodb表的數據、索引、插入緩衝、鎖信息和數據字典信息。innodb允許有多個緩衝池實例,每個頁根據哈希值平均分配到不同緩衝池實例中,以減少數據庫內部資源競爭,增加併發性能。
    2. 重做日誌緩衝是事務在內存中的緩衝,事務操作會先寫日誌到重做日誌緩衝中,再由主線程將日誌數據刷到磁盤中。
    3. 高速查詢緩存。由於查詢緩衝數據變化率高,建議在生產中關閉。
2.1.1 緩衝池的組織結構
    緩衝池中的數據按照段、區、頁的結構進行組織。段分爲數據段、索引段、回滾段等信息。一個段由N個區加32個頁組成,一個區由64個連續的頁組成,大小爲1MB,每個頁的大小爲16K,頁是mysql數據組織的最小單位。
每個頁在內存中爲分配的一個buffer。按照buffer的狀態可以分爲 free buffer、clean buffer、dirty buffer。通過字面意思可理解爲從未使用過的buffer,內存buffer與磁盤數據頁一致的buffer,內存中數據未刷到磁盤的buffer。
這些buffer在內存中是被LRU雙向鏈表組織起來的。根據buffer的狀態可分爲三個LRU鏈表:free list、lru list、flush list。這些list將頻繁使用的頁放在鏈表前端,當內存不足時會釋放鏈表尾端的頁。當新的頁被讀入內存時,會將buffer插入到鏈表的mid位置,該位置可由參數控制。這樣做主要爲了保證熱點數據不被刷回磁盤
free list:將那些free狀態的buffer都串聯起來,每次把page調到內存中時,會從free list獲取buffer,如果不夠用了再從lru list和flush list釋放buffer
lru list: 將與磁盤數據保持一致的頁加入到此鏈表中。每次從free list獲取到頁後會加入到lru list中來,當頁不夠時在從list末尾淘汰頁內存。
flush list: 將dirty buffer串聯起來,爲了方便刷新線程將髒數據刷回磁盤。那些經常被修改的髒頁會暫時不加入到該鏈表中以提高i/o效率。
2.1.2 重做日誌緩衝
    innodb存儲引擎首先將重做日誌信息放入到這個緩衝區,然後按照一定的頻率將其刷新到重做日誌文件。默認情況下至少有2個redo log文件,兩個文件相互覆蓋,在切換文件時候會觸發檢查點技術,將髒頁刷回磁盤。
2.1.3 檢查點技術
    檢查點技術就是在某些特定條件下會觸發對頁的檢查和標記,對於標記的髒頁需要將其同步回磁盤。檢查點技術觸發將頁刷新會磁盤的操作,所以該技術主要評估什麼條件下應該觸發刷新髒頁的操作。檢查點技術主要解決三個問題,縮短數據庫恢復時間;緩衝池不夠用時,將髒頁刷新到磁盤,重做日誌不可用時刷新髒頁。
sharp checkpoint
    在數據庫關閉時將所有髒頁刷回磁盤
fuzzy checkpoint
    只刷新一部分髒頁,觸發條件有 主線程檢查:主線程每秒和每十秒都會刷一定數量的髒頁
    flush lru list檢查:lru列表需要確保有100個空閒也,所以當頁面不足需要釋放空閒頁的時候,如果釋放頁是髒頁需要觸發刷新操作,這個過程會阻塞用戶線程。
    Async/Sync Flush檢查:在重做日誌不可用的情況,需要強制將一些髒頁刷回磁盤。innodb使用water maker標記需要觸發刷髒頁的條件。
    dirty page too much檢查:在緩衝池中髒頁比例到達一定閾值時刷新一部分髒頁到磁盤。
    
2.2 線程工作
    innodb的後臺線程主要分爲 1個master thread負責將緩衝區數據同步到磁盤。 IO Thread,主要有4個read thread 4個wirte thread,1個insert buffer thread,1個log IO thread。1個清除undolog的purge thread,1個刷髒頁的page cleaner thread
2.2.1 master thread
    主後臺線程主要分爲每秒任務,每10秒任務和4循環。主Loop, 後臺loop,刷新loop,掛起loop. 其中每秒任務和每十秒任務在主Loop中完成。
    每秒任務:1.日誌緩衝刷新到磁盤(即使這個事務還未提交、總是執行) 2.合併插入緩衝(前1秒io小於5次) 3. 至多刷新100個髒頁到磁盤(髒頁數量超過比例) 4. 沒有用戶活動切換的後臺loop
    每10秒任務:1. 日誌緩衝刷新到磁盤 2. 合併最多5個插入緩衝 3. 刪除無用的undo頁 4 刷100個或10個髒頁 5 刷100個髒頁(前10秒IO小於200次)
    後臺loop: 1.合併插入緩衝 2. 刪除無用的undo頁 3 刷髒頁(可能調到flush loop中) 4 調回到主循環。
    flush loop: 1 刷髒頁 2. 無活動則切換到掛起loop。
2.2.2 IO thread
    innodb中大量使用了aio處理I/O請求,而IO Thread 主要用來處理這些IO請求的回調。
2.2.3 purge thread
    1.1 版本後纔有,用於減小master thread的壓力
2.2.4 page cleaner thread
    1.2.x 版本後纔有,將刷髒頁任務單獨出來,用於減小master。
    
2.3 關鍵特性
    插入緩衝、雙寫、自適應哈希索引,異步IO、刷鄰接頁。這些特性主要爲innodb存儲引擎帶來更好的性能和更高的可靠性。
2.3.1 插入緩衝
    如果索引不是按照順序插入的,那麼插入索引操作可能出現頻繁從磁盤調頁的操作。而輔助索引一般都不是按照順序插入的,爲了提高IO效率,先將輔助索引記錄放入到insert buffer中。在觸發檢查點時才merge到索引頁中,以提高效率。
    insert buffer是一個b+樹的組織結構放在共享表空間中。b+樹的每個葉子節點對應一張表的一個索引,如果插入一條索引記錄,該記錄對應的頁不在內存中,則構造一個search key將其插入到insert buufer b+樹的葉子節點中。構造的記錄中記錄了進入b+樹的順序。
    space記錄了表id,offset記錄了頁偏移量。metadata記錄進入的順序。 insert bitmap追蹤所有的索引頁。
    當發生以下三個條件時觸發merge操作
    1. 輔助索引頁被讀取到緩衝池
    2. insert bitmap追蹤到無可用的索引頁
    3. master thread刷新
2.3.2 雙寫
    爲了防止數據庫宕機導致頁的部分寫失效,採用雙寫機制。innodb分配了2MB的的double writer buffer在數據刷新到磁盤時,將數據複製到雙寫緩衝區,由雙寫緩衝區順序寫入到共享表空間文件,再由雙寫緩衝區離散的寫入磁盤文件中
    由於寫共享表空間是順序寫入磁盤,所以佔用的開銷不是很大,但是保證了可靠性。
2.3.3 自適應哈希索引 
    innodb存儲引擎自動監控表上的索引頁,對於熱點查詢建立哈希索引。哈希索引只需一次查詢即可定位,而B+樹所以需要樹高次查詢。
    觸發條件有:1 以某查詢模式訪問了100次 2 改頁通過該模式訪問了 頁中記錄/16次。
2.3.4 異步IO 
    Native AIO需要操作系統提供支持
2.3.5 刷鄰接頁 
    當刷新一個髒頁時,innodb會檢查該頁所在的區的所有頁,如果是髒頁則一起刷新。對於傳統機械硬盤該模式具有一定優勢。對於固態硬盤可以不啓用。
    
2.4 啓動與關閉
    mysql關閉的時候具有幾種關閉行爲
    0. 完成full purge 和merge insert buffer,並將髒頁刷回磁盤。 這種關閉最慢,但是最安全,啓動最快。
    1. 不完成full purge 和merge insert buffer,只將髒頁刷回磁盤。數據庫默認這種方式
    2. 只講日誌都寫入日誌文件。 這種啓動時需要一定時間進行恢復操作。
    mysql啓動時候可以設置啓動行爲,是否需要進行恢復等行爲。一般生產環境默認需要進行恢復。
    
二、數據庫文件
    數據庫文件主要分爲mysql產生的文件和存儲引擎產生的文件。 mysql文件主要有:參數文件、錯誤日誌、binlog、慢查詢日誌、查詢日誌。innodb存儲引擎文件主要有:表空間文件、重做日誌文件
2.1 參數文件
    參數文件主要描述數據庫啓動的參數配置,如果沒有參數文件mysql將以編譯時默認參數啓動。參數類型分爲靜態和動態,動態參數在mysql實例運行時候可調,分爲全局和會話調整。
2.2 錯誤日誌 
    錯誤日誌是mysql server在運行過程中輸出的錯誤信息。在啓動、運行河關閉的執行過程中出錯,都可以通過錯誤日誌定位原因。錯誤日誌輸出的警告信息可以幫助優化調整數據庫動態參數。
2.3 慢查詢日誌 
    慢查詢日誌記錄了查詢語句時間超過一定閾值的記錄和未走索引的記錄。
2.4 查詢日誌 
    該日誌記錄了全量的客戶端請求操作日誌。不管請求是否得到正確執行。
2.5 二進制日誌
    binlog記錄數據庫的更改操作,常用於主從同步和基於時間點和位置的恢復操作。開啓binlog會有1%性能的下降,但是可以被接受
    記錄binlog的時候會先將日誌寫入binlog緩衝區,在事務提交前將日誌刷新到磁盤中。緩衝區是與事務線程綁定的,緩衝區的大小不宜設置過大和過下,過小則緩衝區不足時將產生一個臨時文件,過大則消耗太多內存。
    在同步磁盤時,可通過參數sync_binlog進行控制。爲0表示同步刷磁盤,不經過緩衝,但是帶來性能的影響。爲1表示每個事務提交前刷磁盤。但是如果此時宕機事務發生回顧,binlog就產生了髒數據。
    binlog_format控制了記錄binlog的日誌格式,statement爲SQL記錄,ROW爲行更改記錄。生產環境建議爲ROW,但是增加了文件大小和網絡開銷。 statement開銷小,但是對於具有隨機函數的語句數據會不一致。
2.6 套接字文件
    unix系統下的本地連接可以採用unix域的套接字方式。這需要一個mysql.sock文件
2.7 表結構定義文件
    mysql具有一個.frm爲後綴的文件,該文件記錄了該表的表結構定義。

2.8 表空間文件
    ibdata 1文件是innodb的共享表空間文件。innodb將存儲的數據按表空間進行存放,可以通過參數設定多個物理文件共同組成一個表空間。
    獨立表空間文件會對每個表生成一個.ibd的文件用於存儲該表的數據、索引等數據和插入緩衝bitmap等數據,其餘數據仍放在共享表空間中。
2.9 重做日誌文件 
    默認情況下innodb會產生2個ib_log_file0和ib_log_file1的文件用於記錄事務日誌,這兩個文件循環覆蓋,用戶在啓動時候恢復數據到關閉前狀態。
    重做日誌文件不宜設置過大和過小,過大則恢復時間長,過下則頻繁觸發檢查點導致抖動。
    由於重做日誌緩衝寫磁盤時,按照512字節即一個扇區的大小進行寫入,由於扇區是最小單位,因此保證寫入必定成功。
    innodb_flush_log_at_trx_commit參數控制事務提交時是否將日誌緩衝數據刷到磁盤。0 等待主線程刷 1 提交事務同步磁盤 2 重做日誌異步刷到磁盤。
2.10 undo log 
    爲了支持mvcc多版本併發控制,需要undo log和回滾段的支持。innodb有一個全局的事務鏈表,在事務開始時會將事務ID放入鏈表中,並通過指針指向undo 記錄。
    undo 日誌記錄了變更前的舊數據存放在共享表空間中,mysql5.6開始使用獨立的undo表空間。    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章