支持事務。
支持行級鎖和表級鎖,能支持更多的併發量。
查詢不加鎖,徹底不影響查詢。
支持崩潰後恢復。
不支持事務。
使用表級鎖,若是數據量大,一個插入操做鎖定表後,其餘請求都將阻塞。
索引,都是實如今存儲引擎層的。html
一、普通索引:最基本的索引,沒有任何約束。
二、惟一索引:具備惟一性約束。
三、主鍵索引:特殊的惟一索引,不容許有空值。
四、複合索引:將多個列組合在一塊兒建立索引,能夠覆蓋多個列。
五、外鍵索引:只有InnoDB類型的表纔可使用外鍵索引,保證數據的一致性、完整性和實現級聯操做。
六、全文索引:MySQL 自帶的全文索引只能用於 InnoDB、MyISAM ,而且只能對英文進行全文檢索,通常使用全文索引引擎。(經常使用的全文索引引擎的解決方案有 Elasticsearch)
- 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樹做爲索引?
從 B-Tree 結構圖中能夠看到,每一個節點中不只包含數據的 key 值,還有 data 值。而每個頁的存儲空間是有限的,若是 data 數據較大時將會致使每一個節點(即一個頁)能存儲的 key 的數量很小,當存儲的數據量很大時一樣會致使 B-Tree 的深度較大,增大查詢時的磁盤 I/O 次數,進而影響查詢效率。在 B+Tree 中,全部數據記錄節點都是按照鍵值大小順序存放在同一層的葉子節點上,而非葉子節點上只存儲 key 值信息,這樣能夠大大加大每一個節點存儲的 key 值數量,下降 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 存儲引擎會遍歷輔助索引找到主鍵。
而後,再經過主鍵在彙集索引中找到完整的行記錄數據。
面試題二、爲何主鍵須要是自增 ID ,又或者爲何主鍵須要帶有時間性關聯?
由於 插入速度嚴重依賴於插入順序,按照主鍵的順序插入是最快的方式,不然將會出現頁分裂,嚴重影響性能。所以,對於 InnoDB 表,咱們通常都會定義一個自增的 ID 列爲主鍵。
一、事務定義了四種事務隔離級別,不一樣數據庫在實現時,產生的併發問題是不一樣的。
READ UNCOMMITTED(讀未提交):事務中的修改,即便沒有提交,對其餘事務也都是可見的。
會致使髒讀。
READ COMMITTED(讀已提交):事務從開始直到提交以前,所作的任何修改對其餘事務都是不可見的。
會致使不可重複讀。
這個隔離級別,也能夠叫作「不可重複讀」。
REPEATABLE READ(可重複讀):一個事務按相同的查詢條件讀取之前檢索過的數據,其餘事務插入了知足其查詢條件的新數據。產生幻行。
會致使幻讀。
SERIALIZABLE(可串行化):強制事務串行執行。
二、MySQL InnoDB 採用 MVCC 來支持高併發,實現結果以下表所示:
<X>
處,MySQL 由於其間隙鎖的特性,致使其在可重複讀的隔離級別下,不存在幻讀問題。也就是說,上圖 <X>
處,須要改爲「否」!!!!SELECT xxx FROM t WHERE id = ? FOR UPDATE
的方式,得到到悲觀鎖,禁止其它事務操做對應的數據,從而解決幻讀問題一、MySQL 的共享鎖和排他鎖,就是讀鎖和寫鎖。
二、表鎖與行鎖:由執行引擎決定
使用行鎖或者表鎖都是使用的悲觀鎖:SELECT ...... FOR UPDATE;
當查詢有明確主鍵時使用的是行鎖;查詢無明確主鍵時使用表鎖
三、悲觀鎖與樂觀鎖
樂觀鎖與悲觀鎖的實現機制?
- 悲觀鎖大多數狀況下依靠數據庫的鎖機制實現,以保證操做最大程度的獨佔性。如: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 將完成表鎖,併發將無從談起。
(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>複製代碼 |
多版本併發控制(MVCC),是一種用來解決讀-寫衝突的無鎖併發控制,也就是爲事務分配單向增加的時間戳,爲每一個修改保存一個版本,版本與事務時間戳關聯,讀操做只讀該事務開始前的數據庫的快照。 這樣在讀操做不用阻塞寫操做,寫操做不用阻塞讀操做的同時,避免了髒讀和不可重複讀。
參考:
一、https://www.cnblogs.com/nullzx/p/8729425.html
二、https://blog.csdn.net/bigtree_3721/article/details/73650601
三、http://svip.iocoder.cn/MySQL/Interview/