1、mysql架構html
mysql是一個單進程多線程架構的數據庫。前端
2、存儲引擎mysql
InnoDB:sql
- 支持事務
- 行鎖
- 讀操做無鎖
- 4種隔離級別,默認爲repeatable
- 自適應hash索引
- 每張表的存儲都是按主鍵的順序記性存放
- 支持全文索引(InnoDB1.2.x - mysql5.6)
- 支持MVCC(多版本併發控制)實現高併發
MyISAM:數據庫
3、InnoDB體系架構多線程

一、後臺線程架構
- Master Thread
- 負責將緩衝池中的數據異步刷新到磁盤,保證數據的一致性
- IO Thread
- Purge Thread
- 回收已經使用並分配的undo頁(事務提交後,其所使用的undolog再也不須要)
二、內存池併發
- 緩衝池(一塊內存區域)
- InnoDB基於磁盤存儲,將記錄按照頁的方式進行管理(因爲基於磁盤,速度較慢,因此須要引入緩衝池提升性能)
- 讀取頁:先從緩衝池獲取,緩衝池沒有,纔會從磁盤獲取
- 修改頁:先寫重作日誌緩衝,再修改緩衝池中的頁,而後以必定的頻率刷新到磁盤(Checkpoint機制),在尚未刷新到磁盤以前,該頁被稱爲髒頁
- innodb_buffer_pool_size設置大小
- 存放對象:索引頁、數據頁、自適應hash索引和lock信息
- 緩衝池能夠配置多個(innodb_buffer_pool_instances),每一個頁根據hash值平均分配到不一樣的緩衝池實例中,用於減小數據庫內部資源競爭
- LRU List
- 將最新的頁放在隊列前端,最近最少使用的放在尾端,當緩衝池不夠用時,將尾端的頁刪除出緩衝池(若是此頁是髒頁,會先刷新到磁盤)。innodb採用的是midpoint技術進行LRU,具體參看《MySQL技術內幕 InnoDB存儲引擎》
- Flush List
- 重作日誌redolog緩衝
- 爲了防止髒頁在刷新到磁盤時宕機,必須先redolog,再修改頁;
- 數據庫發生宕機時,經過redolog完成數據的恢復(ACID-D持久性)
- 默認大小8M,經過innodb_log_buffer_size
- 將redolog緩衝刷新到redolog文件中的時機
- master會將redolog緩衝每隔1s刷新到redolog文件中
- 每一個事物提交
- redolog緩衝池剩餘空間小於1/2
- Checkpoint
- 緩衝池不夠用時,將髒頁刷新到磁盤
- 數據庫宕機時,只須要重作Checkpoint以後的日誌,縮短數據庫的恢復時間
- redolog不可用時,將髒頁刷新到磁盤
4、InnoDB邏輯存儲結構異步

一、表空間高併發
- 默認狀況下,只有一個表空間ibdata1,全部數據存放在這個空間內
- 若是啓用了innodb_file_per_table,則每張表內的數據能夠單獨放到一個表空間內
- 每一個表空間只存放數據、索引和InsertBuffer Bitmap頁,其餘數據還在ibdata1中
二、Segment段(InnoDB引擎本身控制)
- 數據段:B+ tree的葉子節點
- 索引段:B+ tree的非葉子節點
- 回滾段
三、Extent區
- 每一個區的大小爲1M,頁大小爲16KB,即一個區一共有64個連續的頁(區的大小不可調節,頁能夠)
四、Page頁
- InnoDB磁盤管理的最小單位
- 默認每一個頁大小爲16KB,能夠經過innodb_page_size來設置(4/8/16K)
- 每一個頁最多存放7992行數據
五、Row行
5、索引
一、hash索引
- 定位數據只須要一次查找,O(1)
- 自適應hash索引:InnoDB會監控對錶上各個索引頁的查詢,若是觀察到創建hash索引能夠帶來速度提高,則創建hash索引(即InnoDB會自動的根據訪問頻率和模式來自動的爲某些熱點頁創建hash索引)
- 默認是開啓的
- 只可用於等值查詢,不可用於範圍查詢
二、B+樹索引
- 樹的高度通常爲2~4層,須要2~4次查詢(100w和1000w行數據,若是B+ tree都是3層,那麼查詢效率是同樣的)
- B+樹索引能查到的是數據行所在的頁
- 包含彙集索引和輔助索引
三、彙集索引
- 即主鍵索引
- 葉子節點存放的是行記錄數據所在的頁,而頁中的每一行都是完整的行(葉子節點也被稱爲數據頁)
- 針對範圍查詢也比較快
彙集索引圖:
其中,根節點部分的Key:80000001表明主鍵爲1;Pointer:0004表明指向數據頁的頁號(即第4頁);
數據頁節點的的PageOffset:0004表明第4頁,其中存儲的數據是完整的每一行。

四、輔助索引
- 葉子節點存放的也是行記錄數據所在的頁,但仍是頁中存放的不是完整的行,而是僅僅是一對key-value和一個指針,該指針指向相應行數據的彙集索引的主鍵
- 假設輔助索引樹高3層,彙集索引樹爲3層,那麼根據輔助索引查找數據,須要先通過3次IO找到主鍵,再通過3次IO找到行作在的數據頁
- 針對輔助索引的插入和更新操做:輔助索引頁若是在緩衝池中,則插入;若不在,則點放到InsertBuffer對象中,以後在以必定的平率進行InsertBuffer和輔助索引頁子節點的合併
輔助索引圖:
其中,idx_c表示對第c列作了索引;idx_c中的Key:7fffffff表明c列的一個值,實際上是-1;idx_c中的Pointer:80000001表明該行的主鍵是80000001,即1;下面的就是彙集索引部分。

五、聯合索引(多列索引)
- 左邊匹配原則(若是索引爲(a,b),則where a=x能夠用到索引,可是b=x用不到,若是是覆蓋索引有可能會用到)
六、覆蓋索引
- 從輔助索引中直接獲取記錄
- 對於統計操做,例如count(1),有可能聯合索引,右邊也會匹配(優化器本身會作),由於count(1)操做不須要獲取整行的詳細數據,因此不須要去彙集索引的葉子節點去獲取數據,直接在輔助索引樹中就完成了操做
- select username from xxx where username='lisi',若是username是輔助索引,那麼整個查詢在輔助索引樹上就能夠完成,由於輔助索引樹上雖然沒有保存完整的行,可是保存着<username,lisi>這個key-value對;若是select username, age from xxx where username='lisi',那麼就要走彙集索引了
6、鎖
一、latch
- 保證併發線程操做臨界資源的正確性
- 自旋鎖,自旋指定的次數後,若還沒獲取到鎖,則進入等待狀態,等待被喚醒
二、lock
- 事務鎖,鎖定的多是表、頁或行
- 釋放點:事務commit或rollback
- 兩種標準的行級鎖
- 共享鎖:S lock,事務T1獲取了r行的S鎖,事務T2也能夠獲取r行的S鎖
- 排他鎖:X lock,事務T1獲取了r行的S鎖,事務T2就不能獲取r行的X鎖;事務T1獲取了r行的X鎖,事務T2就不能獲取r行的X/S鎖
7、事務
一、隔離級別
- 讀不提交
- 讀而且提交
- 可避免髒讀:一個事務讀到另外一個事務沒有提交的數據,若是另外一個事務發生回滾,第一個事務讀到的數據就是垃圾數據
- 可重複讀
- 會有幻讀,InnoDB經過Next-Key Lock解決了
- 幻讀:指兩次執行同一條 select 語句會出現不一樣的結果,第二次讀會增長一數據行,並無說這兩次執行是在同一個事務中。使用表鎖便可避免。
- 可避免不可重複讀:在同一個事務中兩條如出一轍的 select 語句的執行結果的比較。若是先後執行的結果同樣,則是可重複讀;若是先後的結果能夠不同,則是不可重複讀。一般是發生了update。增長讀取時的共享鎖(禁止修改)便可避免。
- 默認的事務隔離級別
- 序列化
這裏有美團的一篇文章,很是好:http://tech.meituan.com/mysql-index.html
補充:摘自:https://tech.meituan.com/mysql-index.html
1、B+樹結構:

2、從B+樹查找數據流程

3、B+樹性質
