本文總結了MySql 索引、鎖、事務知識點。分享給大家供大家參考,具體如下:
索引,類似書籍的目錄,可以根據目錄的某個頁碼立即找到對應的記錄。
索引的優點:
索引的缺點:
注意點:小表使用全表掃描更快,中大表才使用索引。超級大表索引基本無效。
索引從實現上說,分成 2 種:聚集索引和輔助索引(也叫二級索引或者非聚集索引)
從功能上說,分為 6 種:普通索引,唯一索引,主鍵索引,復合索引,外鍵索引,全文索引。
詳細說說 6 種索引:
注意:主鍵就是唯一索引,但是唯一索引不一定是主鍵,唯一索引可以為空,但是空值只能有一個,主鍵不能為空。
另外,InnoDB 通過主鍵聚簇數據,如果沒有定義主鍵且沒有定義聚集索引, MySql 會選擇一個唯一的非空索引代替,如果沒有這樣的索引,會隱式定義個 6 字節的主鍵作為聚簇索引,用戶不能查看或訪問。
簡單點說:
MySql 將數據按照頁來存儲,默認一頁為 16kb,當你在查詢時,不會只加載某一條數據,而是將這個數據所在的頁都加載到 pageCache 中,這個其實和 OS 的就近訪問原理類似。
MySql 的索引使用 B+ 樹結構。在說 B+ 樹之前,先說說 B 樹,B 樹是一個多路平衡查找樹,相較于普通的二叉樹,不會發生極度不平衡的狀況,同時也是多路的。
B 樹的特點是:他會將數據也保存在非頁子節點。
看圖可知:
而這個特點會導致非頁子節點不能存儲大量的索引。
而 B+ Tree 就是針對這個對 B tree 做了優化。如下圖所示:
我們看到,B+ Tree 將所有的 data 數據都保存到了葉子節點中,非也子節點只保存索引和指針。
我們假設一個非頁子節點是 16kb,每個索引,即主鍵是 bigint,即 8b,指針為 8b。那么每頁能存儲大約 1000 個索引(16kb/ 8b + 8b).
而一顆 3 層的 B+樹能夠存儲多少索引呢?如下圖:
大約能夠存儲 10 億個索引。通常 B+ 樹的高度在 2-4 層,由于 MySql 在運行時,根節點是常駐內存的,因此每次查找只需要大約 2 -3 次 IO。可以說,B+ 樹的設計,就是根據機械磁盤的特性來進行設計的。
知道了索引的設計,我們能夠知道另外一些信息:
那么,如果項目中使用了分庫分表,我們通常都會需要一個主鍵進行 sharding,那怎么辦呢?在實現上,我們可以保留自增主鍵,而邏輯主鍵用來作為唯一索引即可。
關于 Mysql 的鎖,各種概念就會噴涌而出,事實上,鎖有好幾種維度,我們來解釋一下。
1. 類型維度
類型細分:
意向共享鎖
意向排他(互斥)鎖
2. 鎖的粒度(粒度維度)
3. 鎖的算法(算法維度)
4. 默認的讀操作,上鎖嗎?
可以選擇手動上鎖:select xxxx for update (排他鎖); select xxxx lock in share mode(共享鎖),稱之為“一致性鎖定讀”。
使用鎖之后,就能在 RR 級別下,避免幻讀。當然,默認的 MVCC 讀,也能避免幻讀。
既然 RR 能夠防止幻讀,那么,SERIALIZABLE 有啥用呢?
防止丟失更新。例如下圖:
這個時候,我們必須使用 SERIALIZABLE 級別進行串行讀取。
最后,行鎖的實現原理就是鎖住聚集索引,如果你查詢的時候,沒有正確地擊中索引,MySql 優化器將會拋棄行鎖,使用表鎖。
事務是數據庫永恒不變的話題, ACID:原子性,一致性,隔離性,持久性。
四個特性,最重要的就是一致性。而一致性由原子性,隔離性,持久性來保證。
然后再說隔離性。
隔離級別:
每個級別都會解決不同的問題,通常是3 個問題:臟讀,不可重復讀,幻讀。一張經典的圖:
這里有個注意點,關于幻讀,在數據庫規范里,RR 級別會導致幻讀,但是,由于 Mysql 的優化,MySql 的 RR 級別不會導致幻讀:在使用默認的 select 時,MySql 使用 MVCC 機制保證不會幻讀;你也可以使用鎖,在使用鎖時,例如 for update(X 鎖),lock in share mode(S 鎖),MySql 會使用 Next-Key Lock 來保證不會發生幻讀。前者稱為快照讀,后者稱為當前讀。
原理剖析:
那 RR 和 Serializble 有什么區別呢?答:丟失更新。本文關于鎖的部分已經提到。
MVCC 介紹:全稱多版本并發控制。
innoDB 每個聚集索引都有 4 個隱藏字段,分別是主鍵(RowID),最近更改的事務 ID(MVCC 核心),Undo Log 的指針(隔離核心),索引刪除標記(當刪除時,不會立即刪除,而是打標記,然后異步刪除);
本質上,MVCC 就是用 Undo Log 鏈表實現。
MVCC 的實現方式:事務以排它鎖的方式修改原始數據,把修改前的數據存放于 Undo Log,通過回滾指針與數據關聯,如果修改成功,什么都不做,如果修改失敗,則恢復 Undo Log 中的數據。
多說一句,通常我們認為 MVCC 是類似樂觀鎖的方式,即使用版本號,而實際上,innoDB 不是這么實現的。當然,這不影響我們使用 MySql。
更多關于MySQL相關內容感興趣的讀者可查看本站專題:《MySQL索引操作技巧匯總》、《MySQL常用函數大匯總》、《MySQL日志操作技巧大全》、《MySQL事務操作技巧匯總》、《MySQL存儲過程技巧大全》及《MySQL數據庫鎖相關技巧匯總》
希望本文所述對大家MySQL數據庫計有所幫助。
新聞熱點
疑難解答