MySQL 總結知識

本篇文章主要是整理一下mysql的基礎知識 


1、mysql的執行引擎

  •  一、innodb: 默認的存儲引擎是 InnoDB ,而且也是最主流的選擇 

 支持事務。 
 支持行級鎖和表級鎖,能支持更多的併發量。 
 查詢不加鎖,徹底不影響查詢。 
 支持崩潰後恢復。

  • 二、MyISAM:在 MySQL5.1 以及以前的版本,默認的存儲引擎是 MyISAM ,可是目前已經再也不更新 

 不支持事務。 
 使用表級鎖,若是數據量大,一個插入操做鎖定表後,其餘請求都將阻塞。 

2、索引

索引,都是實如今存儲引擎層的。html

一、主要有六種類型:

一、普通索引:最基本的索引,沒有任何約束。 
二、惟一索引:具備惟一性約束。 
三、主鍵索引:特殊的惟一索引,不容許有空值。
四、複合索引:將多個列組合在一塊兒建立索引,能夠覆蓋多個列。 
五、外鍵索引:只有InnoDB類型的表纔可使用外鍵索引,保證數據的一致性、完整性和實現級聯操做。 
六、全文索引:MySQL 自帶的全文索引只能用於 InnoDB、MyISAM ,而且只能對英文進行全文檢索,通常使用全文索引引擎。(經常使用的全文索引引擎的解決方案有 Elasticsearch) 


二、MySQL 索引的「使用」注意事項? 

- 0、 應儘可能避免在 where 子句中對字段進行 null 值判斷,不然將致使引擎放棄使用索引而進行全表掃描 。 
- 一、 應儘可能避免在 WHERE 子句中使用 != 或 <>操做符, 不然引擎將放棄使用索引而進行全表掃描。 優化器將沒法經過索引來肯定將要命中的行數,所以須要搜索該表的全部行。 注意,column IS NULL 也是不可使用索引的。 
- 二、 應儘可能避免在 where 子句中使用 or 來鏈接條件,若是一個字段有索引,一個字段沒有索引,將致使引擎放棄使用索引而進行全表掃描。 
- 三、 應儘可能避免在 WHERE 子句中對字段進行表達式操做,這將致使引擎放棄使用索引而進行全表掃描。 
- 四、 應儘可能避免在 WHERE 子句中對字段進行函數操做,這將致使引擎放棄使用索引而進行全表掃描。 
- 五、 不要在 WHERE 子句中的 = 左邊進行函數、算術運算或其餘表達式運算,不然系統將可能沒法正確使用索引。 
- 六、 儘可能使用數字型字段,若只含數值信息的字段儘可能不要設計爲字符型,這會下降查詢和鏈接的性能,並會增長存儲開銷。這是由於引擎在處理查詢和鏈接時會逐個比較字符串中每個字符,而對於數字型而言只須要比較一次就夠了。 
- 七、 列類型是字符串類型,查詢時必定要給值加引號,不然索引失效。
- 八、 LIKE 查詢,% 不能在前,由於沒法使用索引。若是須要模糊匹配,可使用全文索引。   
- 九、 儘可能的擴展索引,不要新建索引
- 十、 複合索引遵循前綴原則。索引的最左匹配特性


三、索引結構

爲了描述B-Tree,首先定義一條記錄爲一個二元組 [key, data] ,key 爲記錄的鍵值,對應表中的主鍵值,data 爲一行記錄中除主鍵外的數據。
mysql

InnoDB存儲引擎就是用 B+Tree 實現其索引結構。面試

B+樹結構中有:     sql

  • 非葉子節點只存儲鍵值信息,
  • 數據所有冗餘到了葉子節點,
  • 並且全部葉子節點之間都有一個鏈指針,因此支持範圍查找
  1. 在 B+Tree 中,全部數據記錄節點都是按照鍵值大小順序存放在同一層的葉子節點上,而非葉子節點上只存儲 key 值信息,這樣能夠大大加大每一個節點存儲的 key 值數量,下降 B+Tree 的高度。
  2. 一般在 B+Tree 上有兩個頭指針,一個指向根節點,另外一個指向關鍵字最小的葉子節點,並且全部葉子節點(即數據節點)之間是一種鏈式環結構。所以能夠對 B+Tree 進行兩種查找運算:一種是對於主鍵的範圍查找和分頁查找,另外一種是從根節點開始,進行隨機查找。
  3. 在B-樹基礎上,爲葉子結點增長鏈表指針,全部關鍵字都在葉子結點中出現,非葉子結點做爲葉子結點的索引;B+樹老是到葉子結點才命中;
面試題1:爲何不用B樹做爲索引?
從 B-Tree 結構圖中能夠看到,每一個節點中不只包含數據的 key 值,還有 data 值。而每個頁的存儲空間是有限的,若是 data 數據較大時將會致使每一個節點(即一個頁)能存儲的 key 的數量很小,當存儲的數據量很大時一樣會致使 B-Tree 的深度較大,增大查詢時的磁盤 I/O 次數,進而影響查詢效率。在 B+Tree 中,全部數據記錄節點都是按照鍵值大小順序存放在同一層的葉子節點上,而非葉子節點上只存儲 key 值信息,這樣能夠大大加大每一個節點存儲的 key 值數量,下降 B+Tree 的高度。


四、B-Tree 有哪些索引類型

在 B+Tree 中,根據葉子節點的內容,索引類型分爲主鍵索引非主鍵索引
數據庫

innodb中的主鍵索引和實際數據綁定在一塊兒,也就是說Innodb的一個表必定要有主鍵索引。若是一個表沒有手動創建主鍵索引,Innodb會查看有沒有惟一索引,若是有,則選用惟一索引做爲主鍵索引;若是連惟一索引也沒有,則會默認創建一個隱蔽的主鍵索引,這個隱形字段長度爲6個字節,類型爲長整形(用戶不可見)。併發

1)主鍵索引:
函數

在InnoDB中,表數據文件自己就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,所以InnoDB表數據文件自己就是主索引。
高併發

(圖inndb主鍵索引)是InnoDB主索引(同時也是數據文件)的示意圖,能夠看到葉節點包含了完整的數據記錄。這種索引叫作彙集索引。由於InnoDB的數據文件自己要按主鍵彙集,因此InnoDB要求表必須有主鍵(MyISAM能夠沒有)性能


2). InnoDB的輔助索引優化

InnoDB的全部輔助索引都引用主鍵做爲data域。例如,下圖爲定義在Col3上的一個輔助索引:


總結:

  • 主鍵索引的葉子節點存的數據是整行數據( 即具體數據 )。在 InnoDB 裏,主鍵索引也被稱爲彙集索引(clustered index)。
  • 非主鍵索引的葉子節點存的數據是整行數據的主鍵,鍵值是索引。在 InnoDB 裏,非主鍵索引也被稱爲輔助索引(secondary index)。  
  • 當經過輔助索引來查詢數據時,須要進過兩步:
           首先,InnoDB 存儲引擎會遍歷輔助索引找到主鍵。 
           而後,再經過主鍵在彙集索引中找到完整的行記錄數據。
    面試題二、爲何主鍵須要是自增 ID ,又或者爲何主鍵須要帶有時間性關聯?
    由於 插入速度嚴重依賴於插入順序,按照主鍵的順序插入是最快的方式,不然將會出現頁分裂,嚴重影響性能。所以,對於 InnoDB 表,咱們通常都會定義一個自增的 ID 列爲主鍵。


    3、事務

    (一)、事務的特性  :指的是 ACID

    1. 原子性 Atomicity :一個事務(transaction)中的全部操做,或者所有完成,或者所有不完成,不會結束在中間某個環節。事務在執行過程當中發生錯誤,會被恢復(Rollback)到事務開始前的狀態,就像這個事務歷來沒有執行過同樣。即,事務不可分割、不可約簡。
    2. 一致性 Consistency :在事務開始以前和事務結束之後,數據庫的完整性沒有被破壞。
    3. 隔離性 Isolation :數據庫容許多個併發事務同時對其數據進行讀寫和修改的能力,隔離性能夠防止多個事務併發執行時因爲交叉執行而致使數據的不一致。事務隔離分爲不一樣級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和串行化(Serializable)。
    4. 持久性 Durability :事務處理結束後,對數據的修改就是永久的,即使系統故障也不會丟失。

    (二)、事務的隔離級別

    一、事務定義了四種事務隔離級別,不一樣數據庫在實現時,產生的併發問題是不一樣的。

    • READ UNCOMMITTED(讀未提交):事務中的修改,即便沒有提交,對其餘事務也都是可見的。

      會致使髒讀。

    • READ COMMITTED(讀已提交):事務從開始直到提交以前,所作的任何修改對其餘事務都是不可見的。

      會致使不可重複讀。

      這個隔離級別,也能夠叫作「不可重複讀」。

    • REPEATABLE READ(可重複讀):一個事務按相同的查詢條件讀取之前檢索過的數據,其餘事務插入了知足其查詢條件的新數據。產生幻行。

      會致使幻讀。

    • SERIALIZABLE(可串行化):強制事務串行執行。

    二、MySQL InnoDB 採用 MVCC 來支持高併發,實現結果以下表所示:


    • MySQL 默認的事務隔離級別爲可重複讀(repeatable-read) 。
    • 上圖的 <X> 處,MySQL 由於其間隙鎖的特性,致使其在可重複讀的隔離級別下,不存在幻讀問題。也就是說,上圖 <X> 處,須要改爲「否」!!!!
    • 有些資料說可重複讀解決了幻讀,實際是存在的,能夠經過 SELECT xxx FROM t WHERE id = ? FOR UPDATE 的方式,得到到悲觀鎖,禁止其它事務操做對應的數據,從而解決幻讀問題


    4、mysql鎖機制

    一、MySQL 的共享鎖和排他鎖,就是讀鎖和寫鎖。

    二、表鎖與行鎖:由執行引擎決定

    使用行鎖或者表鎖都是使用的悲觀鎖:SELECT ...... FOR UPDATE;

    當查詢有明確主鍵時使用的是行鎖;查詢無明確主鍵時使用表鎖

    • 表鎖:系統開銷最小,會鎖定整張表,MyIsam 使用表鎖。
    • 行鎖:最大程度的支持併發處理,可是也帶來了最大的鎖開銷,InnoDB 使用行鎖。

    三、悲觀鎖與樂觀鎖

    • 樂觀鎖:能夠讀,不能寫 
    • 悲觀鎖:不能讀寫,就是上面看到的共享鎖和排他鎖

    樂觀鎖與悲觀鎖的實現機制?
    • 悲觀鎖大多數狀況下依靠數據庫的鎖機制實現,以保證操做最大程度的獨佔性。如:SELECT xxx FROM t WHERE id = ? FOR UPDATE 的方式
    • 樂觀鎖,大可能是基於數據版本( Version )記錄機制實現:樂觀鎖,實際就是經過版本號,從而實現 CAS 原子性更新。

    四、死鎖

    死鎖發生在當多個進程訪問同一數據庫時,其中每一個進程擁有的鎖都是其餘進程所需的,由此形成每一個進程都沒法繼續下去。簡單的說,進程 A 等待進程 B 釋放他的資源,B 又等待 A 釋放他的資源,這樣就互相等待就造成死鎖。

    下列方法有助於最大限度地下降死鎖:

    • 設置得到鎖的超時時間。 經過超時,至少保證最差狀況下,能夠有退出的口子。
    •  按同一順序訪問對象。 這個是最重要的方式。 
    • 避免事務中的用戶交互。 
    • 保持事務簡短並在一個批處理中。 
    • 使用低隔離級別。
    • 使用綁定鏈接。

    面試題:MySQL 中InnoDB引擎的行鎖是經過加在什麼上完成(或稱實現)的?

     InnoDB 是基於索引來完成行鎖。
    例如:SELECT * FROM tab_with_index WHERE id = 1 FOR UPDATE 
    FOR UPDATE 能夠根據條件來完成行鎖鎖定,而且 id 是有索引鍵的列;若是 id 不是索引鍵,那麼 InnoDB 將完成表鎖,併發將無從談起。

    5、MySQL 查詢執行順序

    (1)     SELECT
    (2)     DISTINCT <select_list>
    (3)     FROM <left_table>
    (4)     <join_type> JOIN <right_table>
    (5)     ON <join_condition>
    (6)     WHERE <where_condition>
    (7)     GROUP BY <group_by_list>
    (8)     HAVING <having_condition>
    (9)     ORDER BY <order_by_condition>
    (10)    LIMIT <limit_number>複製代碼

    6、什麼是 MVCC

    多版本併發控制(MVCC),是一種用來解決讀-寫衝突的無鎖併發控制,也就是爲事務分配單向增加的時間戳,爲每一個修改保存一個版本,版本與事務時間戳關聯,讀操做只讀該事務開始前的數據庫的快照。 這樣在讀操做不用阻塞寫操做,寫操做不用阻塞讀操做的同時,避免了髒讀和不可重複讀。

    7、MySQL SQL 優化





    參考:

    一、https://www.cnblogs.com/nullzx/p/8729425.html

    二、https://blog.csdn.net/bigtree_3721/article/details/73650601

    三、http://svip.iocoder.cn/MySQL/Interview/

    相關文章
    相關標籤/搜索